aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.drone.yml24
-rw-r--r--.drone.yml.sig1
-rw-r--r--compiler/src/dotty/tools/backend/jvm/LabelDefs.scala45
-rw-r--r--compiler/src/dotty/tools/dotc/Run.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Desugar.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Positioned.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/TreeInfo.scala22
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Trees.scala188
-rw-r--r--compiler/src/dotty/tools/dotc/ast/tpd.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala22
-rw-r--r--compiler/src/dotty/tools/dotc/config/ScalaSettings.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/Phases.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/printing/package.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala27
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Mixin.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PostTyper.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Dynamic.scala66
-rw-r--r--compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Inliner.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala23
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala89
-rw-r--r--compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala12
-rw-r--r--compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala32
-rw-r--r--doc-tool/resources/_includes/header.html1
-rw-r--r--doc-tool/resources/_includes/scala-logo.svg30
-rw-r--r--doc-tool/resources/_includes/toc.html11
-rw-r--r--doc-tool/resources/_layouts/api-page.html171
-rw-r--r--doc-tool/resources/_layouts/blog-page.html28
-rw-r--r--doc-tool/resources/_layouts/doc-page.html8
-rw-r--r--doc-tool/resources/_layouts/index.html4
-rw-r--r--doc-tool/resources/_layouts/main.html71
-rw-r--r--doc-tool/resources/_layouts/sidebar.html49
-rw-r--r--doc-tool/resources/css/api-page.css139
-rw-r--r--doc-tool/resources/css/color-brewer.css71
-rw-r--r--doc-tool/resources/css/dottydoc.css330
-rw-r--r--doc-tool/resources/index.md5
-rw-r--r--doc-tool/resources/js/highlight.pack.js2
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala37
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocDriver.scala59
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocFrontEnd.scala17
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DottyDoc.scala84
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/Main.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/api/java/Dottydoc.java63
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/api/scala/Dottydoc.scala49
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala29
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala162
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala33
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/LinkCompanionsPhase.scala46
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala101
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/PackageObjectsPhase.scala35
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/SortMembersPhase.scala33
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala26
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/UsecasePhase.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala314
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/BodyEntities.scala4
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala148
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/CommentCleaner.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala691
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/CommentRegex.scala2
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala (renamed from doc-tool/src/dotty/tools/dottydoc/model/comment/BodyParsers.scala)84
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala83
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala549
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/entities.scala87
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/factories.scala133
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/internal.scala72
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/java.scala223
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/json.scala93
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/references.scala20
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/BlogPost.scala64
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala90
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/MapOperations.scala25
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownCodeBlockVisitor.scala19
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownLinkVisitor.scala42
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala178
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/ResourceFinder.scala16
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala409
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala112
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/Yaml.scala23
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/filters.scala42
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala221
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/MemberLookup.scala40
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/OutputWriter.scala125
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/mutate.scala6
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/syntax.scala11
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/traversing.scala (renamed from doc-tool/src/dotty/tools/dottydoc/util/Traversing.scala)18
-rw-r--r--doc-tool/test/CommentCleanerTest.scala83
-rw-r--r--doc-tool/test/ConstructorTest.scala38
-rw-r--r--doc-tool/test/DottyDocTest.scala (renamed from doc-tool/test/BaseTest.scala)5
-rw-r--r--doc-tool/test/GenDocs.scala46
-rw-r--r--doc-tool/test/MarkdownTests.scala309
-rw-r--r--doc-tool/test/PackageStructure.scala11
-rw-r--r--doc-tool/test/SimpleComments.scala3
-rw-r--r--doc-tool/test/SourceFileOps.scala51
-rw-r--r--doc-tool/test/TemplateErrorTests.scala32
-rw-r--r--doc-tool/test/UsecaseTest.scala12
-rw-r--r--doc-tool/test/WhitelistedStdLib.scala14
-rw-r--r--doc-tool/test/dotty/tools/dottydoc/staticsite/PageTests.scala102
-rw-r--r--doc-tool/test/dotty/tools/dottydoc/staticsite/SiteTests.scala100
-rw-r--r--docs/Gemfile27
-rw-r--r--docs/_config.yml6
-rw-r--r--docs/_includes/faq.html8
-rw-r--r--docs/_includes/features.html8
-rw-r--r--docs/_includes/getting-started.html2
-rw-r--r--docs/_includes/logo-page.html4
-rw-r--r--docs/_includes/scala-logo.html19
-rw-r--r--docs/_includes/toc.html43
-rw-r--r--docs/_layouts/blog.html17
-rw-r--r--docs/_layouts/default.html61
-rw-r--r--docs/_layouts/index.html38
-rw-r--r--docs/_layouts/search.html17
-rw-r--r--docs/blog/_posts/2015-10-23-dotty-compiler-bootstraps.md3
-rw-r--r--docs/blog/index.html2
-rw-r--r--docs/css/default.css2
-rw-r--r--docs/css/main.scss298
-rw-r--r--docs/docs/contributing/eclipse.md4
-rw-r--r--docs/docs/contributing/getting-started.md12
-rw-r--r--docs/docs/contributing/intellij-idea.md4
-rw-r--r--docs/docs/contributing/workflow.md15
-rw-r--r--docs/docs/index.md2
-rw-r--r--docs/docs/internals/backend.md27
-rw-r--r--docs/docs/internals/benchmarks.md7
-rw-r--r--docs/docs/internals/classpaths.md5
-rw-r--r--docs/docs/internals/contexts.md4
-rw-r--r--docs/docs/internals/core-data-structures.md (renamed from docs/dotc-internals/core-data-structures.md)8
-rw-r--r--docs/docs/internals/dotc-scalac.md2
-rw-r--r--docs/docs/internals/higher-kinded-v2.md2
-rw-r--r--docs/docs/internals/overall-structure.md2
-rw-r--r--docs/docs/internals/periods.md2
-rw-r--r--docs/docs/internals/syntax.md2
-rw-r--r--docs/docs/internals/type-system.md2
-rw-r--r--docs/docs/usage/cbt-projects.md4
-rw-r--r--docs/docs/usage/dottydoc.md260
-rw-r--r--docs/docs/usage/migrating.md18
-rw-r--r--docs/docs/usage/sbt-projects.md2
-rw-r--r--docs/images/olivier.jpegbin0 -> 10202 bytes
-rw-r--r--docs/images/scala-logo.svg49
-rw-r--r--docs/index.html17
-rw-r--r--docs/js/highlight.pack.js2
-rwxr-xr-xdocs/js/scrollreveal.min.js1
-rw-r--r--docs/search.html35
-rw-r--r--docs/sidebar.yml49
-rw-r--r--library/src/scala/Selectable.scala8
-rw-r--r--library/src/scala/reflect/Selectable.scala73
-rw-r--r--project/Build.scala42
-rwxr-xr-xproject/scripts/genDocs68
-rw-r--r--sbt-bridge/src/xsbt/ScaladocInterface.scala26
-rw-r--r--tests/neg/i1568.scala3
-rw-r--r--tests/neg/structural.scala11
-rw-r--r--tests/neg/valueclasses-impl-restrictions.scala19
-rw-r--r--tests/neg/zoo.scala14
-rw-r--r--tests/pos/backquoted_type_operator.scala4
-rw-r--r--tests/pos/f-bounded-case-class.scala1
-rw-r--r--tests/pos/i1723.scala8
-rw-r--r--tests/pos/i1866.scala5
-rw-r--r--tests/pos/zoo2.scala45
-rw-r--r--tests/repl/errmsgs.check7
-rw-r--r--tests/run/functionXXL.scala (renamed from tests/pos/functionXXL.scala)4
-rw-r--r--tests/run/i1569.check2
-rw-r--r--tests/run/i1569.scala5
-rw-r--r--tests/run/i1915.scala9
-rw-r--r--tests/run/structural.scala25
-rw-r--r--tests/run/structuralNoSuchMethod.check1
-rw-r--r--tests/run/structuralNoSuchMethod.scala23
-rw-r--r--tests/run/t10170.check1
-rw-r--r--tests/run/t10170.scala7
-rw-r--r--tests/untried/neg/valueclasses-impl-restrictions.scala29
180 files changed, 6188 insertions, 2523 deletions
diff --git a/.drone.yml b/.drone.yml
index 16a5aff49..544eae07b 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -6,6 +6,30 @@ pipeline:
- ln -s /var/cache/drone/scala-scala scala-scala
- ./scripts/update-scala-library
- sbt -J-Xmx4096m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m -Ddotty.drone.mem=4096m -ivy /var/cache/drone/ivy2 "${TEST}"
+ when:
+ branch:
+ exclude: gh-pages
+
+ documentation:
+ image: lampepfl/dotty:latest
+ pull: true
+ commands:
+ - ./project/scripts/genDocs "${TEST}" $BOT_PASS
+ when:
+ branch: master
+
+ gitter:
+ image: plugins/gitter
+ when:
+ branch: master
+ status: changed
+
+ slack:
+ image: plugins/slack
+ channel: dotty
+ when:
+ branch: master
+ status: changed
matrix:
TEST:
diff --git a/.drone.yml.sig b/.drone.yml.sig
new file mode 100644
index 000000000..033741bd7
--- /dev/null
+++ b/.drone.yml.sig
@@ -0,0 +1 @@
+eyJhbGciOiJIUzI1NiJ9.cGlwZWxpbmU6CiAgdGVzdDoKICAgIGltYWdlOiBsYW1wZXBmbC9kb3R0eTpsYXRlc3QKICAgIHB1bGw6IHRydWUKICAgIGNvbW1hbmRzOgogICAgICAtIGxuIC1zIC92YXIvY2FjaGUvZHJvbmUvc2NhbGEtc2NhbGEgc2NhbGEtc2NhbGEKICAgICAgLSAuL3NjcmlwdHMvdXBkYXRlLXNjYWxhLWxpYnJhcnkKICAgICAgLSBzYnQgLUotWG14NDA5Nm0gLUotWFg6UmVzZXJ2ZWRDb2RlQ2FjaGVTaXplPTUxMm0gLUotWFg6TWF4TWV0YXNwYWNlU2l6ZT0xMDI0bSAtRGRvdHR5LmRyb25lLm1lbT00MDk2bSAtaXZ5IC92YXIvY2FjaGUvZHJvbmUvaXZ5MiAiJHtURVNUfSIKICAgIHdoZW46CiAgICAgIGJyYW5jaDoKICAgICAgICBleGNsdWRlOiBnaC1wYWdlcwoKICBkb2N1bWVudGF0aW9uOgogICAgaW1hZ2U6IGxhbXBlcGZsL2RvdHR5OmxhdGVzdAogICAgcHVsbDogdHJ1ZQogICAgY29tbWFuZHM6CiAgICAgIC0gLi9wcm9qZWN0L3NjcmlwdHMvZ2VuRG9jcyAiJHtURVNUfSIgJEJPVF9QQVNTCiAgICB3aGVuOgogICAgICBicmFuY2g6IG1hc3RlcgoKICBnaXR0ZXI6CiAgICBpbWFnZTogcGx1Z2lucy9naXR0ZXIKICAgIHdoZW46CiAgICAgIGJyYW5jaDogbWFzdGVyCiAgICAgIHN0YXR1czogY2hhbmdlZAoKICBzbGFjazoKICAgIGltYWdlOiBwbHVnaW5zL3NsYWNrCiAgICBjaGFubmVsOiBkb3R0eQogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKICAgICAgc3RhdHVzOiBjaGFuZ2VkCgptYXRyaXg6CiAgVEVTVDoKICAgIC0gdGVzdAogICAgLSA7cHVibGlzaExvY2FsO2RvdHR5LWJvb3RzdHJhcHBlZC90ZXN0CiAgICAtIHBhcnRlc3Qtb25seS1uby1ib290c3RyYXAgLS1zaG93LWRpZmYgLS12ZXJib3NlCiAgICAtIHBhcnRlc3Qtb25seSAtLXNob3ctZGlmZiAtLXZlcmJvc2UK.8TfJtublnAM4giXtBiyzES25lo61mACbSHnyUv5mosE \ No newline at end of file
diff --git a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
index 371396e36..654507991 100644
--- a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
+++ b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
@@ -37,44 +37,47 @@ import StdNames.nme
/**
* Verifies that each Label DefDef has only a single address to jump back and
- * reorders them such that they are not nested and this address is a fall-through address for JVM
- *
- * ei such code
- *
+ * reorders them such that they are not nested and this address is a
+ * fall-through address for the JVM.
*
+ * ```scala
* <label> def foo(i: Int) = {
* <label> def bar = 0
* <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
* dough(i)
- * }
+ * }
*
* foo(100)
+ * ```
*
- * will get rewritten to
+ * will get rewritten to:
*
- * \
+ * ```scala
* <label> def foo(i: Int) = dough(i)
* <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
* <label> def bar = 2
* foo(100)
+ * ```
*
- * Proposed way to generate this pattern in backend is:
+ * Proposed way to generate this pattern in backend is:
*
- * foo(100)
- * <jump foo>
- * <label> def foo(i: Int) = dough(i)
- * // <jump a> // unreachable
- * <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
- * // <jump a> // unreachable
- * <label> def bar = 2
- * // <jump a> // unreachable
- * <asm point a>
+ * ```scala
+ * foo(100)
+ * <jump foo>
+ * <label> def foo(i: Int) = dough(i)
+ * // <jump a> // unreachable
+ * <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
+ * // <jump a> // unreachable
+ * <label> def bar = 2
+ * // <jump a> // unreachable
+ * <asm point a>
+ * ```
*
- * Unreachable jumps will be eliminated by local dead code analysis.
- * After JVM is smart enough to remove next-line jumps
+ * Unreachable jumps will be eliminated by local dead code analysis.
+ * After JVM is smart enough to remove next-line jumps
*
- * Note that Label DefDefs can be only nested in Block, otherwise no one would be able to call them
- * Other DefDefs are eliminated
+ * Note that Label DefDefs can be only nested in Block, otherwise no one would
+ * be able to call them Other DefDefs are eliminated
*/
class LabelDefs extends MiniPhaseTransform {
def phaseName: String = "labelDef"
diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala
index 0f652ff0b..38bf80bad 100644
--- a/compiler/src/dotty/tools/dotc/Run.scala
+++ b/compiler/src/dotty/tools/dotc/Run.scala
@@ -15,6 +15,7 @@ import reporting.Reporter
import transform.TreeChecker
import rewrite.Rewrites
import java.io.{BufferedWriter, OutputStreamWriter}
+import printing.XprintMode
import scala.annotation.tailrec
import scala.reflect.io.VirtualFile
@@ -95,7 +96,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
val unit = ctx.compilationUnit
val prevPhase = ctx.phase.prev // can be a mini-phase
val squashedPhase = ctx.squashed(prevPhase)
- val treeString = unit.tpdTree.show
+ val treeString = unit.tpdTree.show(ctx.withProperty(XprintMode, Some(())))
ctx.echo(s"result of $unit after $squashedPhase:")
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
index 2e471e046..eda4a12dc 100644
--- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
@@ -353,7 +353,7 @@ object desugar {
for (i <- 0 until arity if nme.selectorName(i) `ne` caseParams(i).name)
yield syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeIdent), caseParams(i).name))
def isRepeated(tree: Tree): Boolean = tree match {
- case PostfixOp(_, nme.raw.STAR) => true
+ case PostfixOp(_, Ident(nme.raw.STAR)) => true
case ByNameTypeTree(tree1) => isRepeated(tree1)
case _ => false
}
@@ -739,23 +739,25 @@ object desugar {
/** Translate infix operation expression left op right
*/
- def makeBinop(left: Tree, op: Name, right: Tree): Tree = {
+ def makeBinop(left: Tree, op: Ident, right: Tree): Tree = {
def assignToNamedArg(arg: Tree) = arg match {
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
case _ => arg
}
- if (isLeftAssoc(op)) {
+ if (isLeftAssoc(op.name)) {
val args: List[Tree] = right match {
case Parens(arg) => assignToNamedArg(arg) :: Nil
case Tuple(args) => args mapConserve assignToNamedArg
case _ => right :: Nil
}
- Apply(Select(left, op), args)
+ val selectPos = Position(left.pos.start, op.pos.end, op.pos.start)
+ Apply(Select(left, op.name).withPos(selectPos), args)
} else {
val x = ctx.freshName().toTermName
+ val selectPos = Position(op.pos.start, right.pos.end, op.pos.start)
new InfixOpBlock(
ValDef(x, TypeTree(), left).withMods(synthetic),
- Apply(Select(right, op), Ident(x)))
+ Apply(Select(right, op.name).withPos(selectPos), Ident(x).withPos(left.pos)))
}
}
@@ -956,25 +958,25 @@ object desugar {
Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
case InfixOp(l, op, r) =>
if (ctx.mode is Mode.Type)
- if (op == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
- else if (op == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
- else AppliedTypeTree(Ident(op), l :: r :: Nil) // op[l, r]
+ if (!op.isBackquoted && op.name == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
+ else if (!op.isBackquoted && op.name == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
+ else AppliedTypeTree(op, l :: r :: Nil) // op[l, r]
else if (ctx.mode is Mode.Pattern)
- Apply(Ident(op), l :: r :: Nil) // op(l, r)
+ Apply(op, l :: r :: Nil) // op(l, r)
else // l.op(r), or val x = r; l.op(x), plus handle named args specially
makeBinop(l, op, r)
case PostfixOp(t, op) =>
- if ((ctx.mode is Mode.Type) && op == nme.raw.STAR) {
+ if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == nme.raw.STAR) {
val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType
Annotated(
AppliedTypeTree(ref(seqType), t),
New(ref(defn.RepeatedAnnotType), Nil :: Nil))
} else {
assert(ctx.mode.isExpr || ctx.reporter.hasErrors, ctx.mode)
- Select(t, op)
+ Select(t, op.name)
}
case PrefixOp(op, t) =>
- Select(t, nme.UNARY_PREFIX ++ op)
+ Select(t, nme.UNARY_PREFIX ++ op.name)
case Parens(t) =>
t
case Tuple(ts) =>
diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala
index bb6817603..51949c6fe 100644
--- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala
@@ -123,6 +123,8 @@ abstract class Positioned extends DotClass with Product {
private def unionPos(pos: Position, xs: List[_]): Position = xs match {
case (p: Positioned) :: xs1 => unionPos(pos union p.pos, xs1)
+ case (xs0: List[_]) :: xs1 => unionPos(unionPos(pos, xs0), xs1)
+ case _ :: xs1 => unionPos(pos, xs1)
case _ => pos
}
diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
index da83d0644..bcda4b92f 100644
--- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -629,6 +629,28 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
case nil =>
Nil
}
+
+ /** Is this a selection of a member of a structural type that is not a member
+ * of an underlying class or trait?
+ */
+ def isStructuralTermSelect(tree: Tree)(implicit ctx: Context) = tree match {
+ case tree: Select =>
+ def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match {
+ case RefinedType(parent, rname, rinfo) =>
+ rname == tree.name || hasRefinement(parent)
+ case tp: TypeProxy =>
+ hasRefinement(tp.underlying)
+ case tp: OrType =>
+ hasRefinement(tp.tp1) || hasRefinement(tp.tp2)
+ case tp: AndType =>
+ hasRefinement(tp.tp1) && hasRefinement(tp.tp2)
+ case _ =>
+ false
+ }
+ !tree.symbol.exists && tree.isTerm && hasRefinement(tree.qualifier.tpe)
+ case _ =>
+ false
+ }
}
object TreeInfo {
diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala
index 798f0f567..bf11a442e 100644
--- a/compiler/src/dotty/tools/dotc/ast/Trees.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala
@@ -3,7 +3,7 @@ package dotc
package ast
import core._
-import Types._, Names._, Flags._, util.Positions._, Contexts._, Constants._
+import Types._, Names._, NameOps._, Flags._, util.Positions._, Contexts._, Constants._
import SymDenotations._, Symbols._, Denotations._, StdNames._, Comments._
import annotation.tailrec
import language.higherKinds
@@ -316,7 +316,7 @@ object Trees {
def namePos =
if (pos.exists)
if (rawMods.is(Synthetic)) Position(pos.point, pos.point)
- else Position(pos.point, pos.point + name.length, pos.point)
+ else Position(pos.point, pos.point + name.stripModuleClassSuffix.length, pos.point)
else pos
}
@@ -334,10 +334,15 @@ object Trees {
extends RefTree[T] {
type ThisTree[-T >: Untyped] = Ident[T]
def qualifier: Tree[T] = genericEmptyTree
+
+ /** Is this a `BackquotedIdent` ? */
+ def isBackquoted: Boolean = false
}
class BackquotedIdent[-T >: Untyped] private[ast] (name: Name)
extends Ident[T](name) {
+ override def isBackquoted: Boolean = true
+
override def toString = s"BackquotedIdent($name)"
}
@@ -1069,95 +1074,100 @@ object Trees {
Template(tree: Tree)(constr, parents, self, body)
}
+ /** Hook to indicate that a transform of some subtree should be skipped */
+ protected def skipTransform(tree: Tree)(implicit ctx: Context): Boolean = false
+
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) {
- def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
- case Ident(name) =>
- tree
- case Select(qualifier, name) =>
- cpy.Select(tree)(transform(qualifier), name)
- case This(qual) =>
- tree
- case Super(qual, mix) =>
- cpy.Super(tree)(transform(qual), mix)
- case Apply(fun, args) =>
- cpy.Apply(tree)(transform(fun), transform(args))
- case TypeApply(fun, args) =>
- cpy.TypeApply(tree)(transform(fun), transform(args))
- case Literal(const) =>
- tree
- case New(tpt) =>
- cpy.New(tree)(transform(tpt))
- case Typed(expr, tpt) =>
- cpy.Typed(tree)(transform(expr), transform(tpt))
- case NamedArg(name, arg) =>
- cpy.NamedArg(tree)(name, transform(arg))
- case Assign(lhs, rhs) =>
- cpy.Assign(tree)(transform(lhs), transform(rhs))
- case Block(stats, expr) =>
- cpy.Block(tree)(transformStats(stats), transform(expr))
- case If(cond, thenp, elsep) =>
- cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
- case Closure(env, meth, tpt) =>
- cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
- case Match(selector, cases) =>
- cpy.Match(tree)(transform(selector), transformSub(cases))
- case CaseDef(pat, guard, body) =>
- cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
- case Return(expr, from) =>
- cpy.Return(tree)(transform(expr), transformSub(from))
- case Try(block, cases, finalizer) =>
- cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
- case SeqLiteral(elems, elemtpt) =>
- cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
- case Inlined(call, bindings, expansion) =>
- cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
- case TypeTree() =>
- tree
- case SingletonTypeTree(ref) =>
- cpy.SingletonTypeTree(tree)(transform(ref))
- case AndTypeTree(left, right) =>
- cpy.AndTypeTree(tree)(transform(left), transform(right))
- case OrTypeTree(left, right) =>
- cpy.OrTypeTree(tree)(transform(left), transform(right))
- case RefinedTypeTree(tpt, refinements) =>
- cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
- case AppliedTypeTree(tpt, args) =>
- cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
- case PolyTypeTree(tparams, body) =>
- cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
- case ByNameTypeTree(result) =>
- cpy.ByNameTypeTree(tree)(transform(result))
- case TypeBoundsTree(lo, hi) =>
- cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
- case Bind(name, body) =>
- cpy.Bind(tree)(name, transform(body))
- case Alternative(trees) =>
- cpy.Alternative(tree)(transform(trees))
- case UnApply(fun, implicits, patterns) =>
- cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
- case EmptyValDef =>
- tree
- case tree @ ValDef(name, tpt, _) =>
- val tpt1 = transform(tpt)
- val rhs1 = transform(tree.rhs)
- cpy.ValDef(tree)(name, tpt1, rhs1)
- case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
- cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
- case tree @ TypeDef(name, rhs) =>
- cpy.TypeDef(tree)(name, transform(rhs))
- case tree @ Template(constr, parents, self, _) =>
- cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
- case Import(expr, selectors) =>
- cpy.Import(tree)(transform(expr), selectors)
- case PackageDef(pid, stats) =>
- cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
- case Annotated(arg, annot) =>
- cpy.Annotated(tree)(transform(arg), transform(annot))
- case Thicket(trees) =>
- val trees1 = transform(trees)
- if (trees1 eq trees) tree else Thicket(trees1)
- }
+ def transform(tree: Tree)(implicit ctx: Context): Tree =
+ if (skipTransform(tree)) tree
+ else tree match {
+ case Ident(name) =>
+ tree
+ case Select(qualifier, name) =>
+ cpy.Select(tree)(transform(qualifier), name)
+ case This(qual) =>
+ tree
+ case Super(qual, mix) =>
+ cpy.Super(tree)(transform(qual), mix)
+ case Apply(fun, args) =>
+ cpy.Apply(tree)(transform(fun), transform(args))
+ case TypeApply(fun, args) =>
+ cpy.TypeApply(tree)(transform(fun), transform(args))
+ case Literal(const) =>
+ tree
+ case New(tpt) =>
+ cpy.New(tree)(transform(tpt))
+ case Typed(expr, tpt) =>
+ cpy.Typed(tree)(transform(expr), transform(tpt))
+ case NamedArg(name, arg) =>
+ cpy.NamedArg(tree)(name, transform(arg))
+ case Assign(lhs, rhs) =>
+ cpy.Assign(tree)(transform(lhs), transform(rhs))
+ case Block(stats, expr) =>
+ cpy.Block(tree)(transformStats(stats), transform(expr))
+ case If(cond, thenp, elsep) =>
+ cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
+ case Closure(env, meth, tpt) =>
+ cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
+ case Match(selector, cases) =>
+ cpy.Match(tree)(transform(selector), transformSub(cases))
+ case CaseDef(pat, guard, body) =>
+ cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
+ case Return(expr, from) =>
+ cpy.Return(tree)(transform(expr), transformSub(from))
+ case Try(block, cases, finalizer) =>
+ cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
+ case SeqLiteral(elems, elemtpt) =>
+ cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
+ case Inlined(call, bindings, expansion) =>
+ cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
+ case TypeTree() =>
+ tree
+ case SingletonTypeTree(ref) =>
+ cpy.SingletonTypeTree(tree)(transform(ref))
+ case AndTypeTree(left, right) =>
+ cpy.AndTypeTree(tree)(transform(left), transform(right))
+ case OrTypeTree(left, right) =>
+ cpy.OrTypeTree(tree)(transform(left), transform(right))
+ case RefinedTypeTree(tpt, refinements) =>
+ cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
+ case AppliedTypeTree(tpt, args) =>
+ cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
+ case PolyTypeTree(tparams, body) =>
+ cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
+ case ByNameTypeTree(result) =>
+ cpy.ByNameTypeTree(tree)(transform(result))
+ case TypeBoundsTree(lo, hi) =>
+ cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
+ case Bind(name, body) =>
+ cpy.Bind(tree)(name, transform(body))
+ case Alternative(trees) =>
+ cpy.Alternative(tree)(transform(trees))
+ case UnApply(fun, implicits, patterns) =>
+ cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
+ case EmptyValDef =>
+ tree
+ case tree @ ValDef(name, tpt, _) =>
+ val tpt1 = transform(tpt)
+ val rhs1 = transform(tree.rhs)
+ cpy.ValDef(tree)(name, tpt1, rhs1)
+ case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
+ cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
+ case tree @ TypeDef(name, rhs) =>
+ cpy.TypeDef(tree)(name, transform(rhs))
+ case tree @ Template(constr, parents, self, _) =>
+ cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
+ case Import(expr, selectors) =>
+ cpy.Import(tree)(transform(expr), selectors)
+ case PackageDef(pid, stats) =>
+ cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
+ case Annotated(arg, annot) =>
+ cpy.Annotated(tree)(transform(arg), transform(annot))
+ case Thicket(trees) =>
+ val trees1 = transform(trees)
+ if (trees1 eq trees) tree else Thicket(trees1)
+ }
def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] =
transform(trees)
diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala
index 433808e8e..565ec5ce2 100644
--- a/compiler/src/dotty/tools/dotc/ast/tpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala
@@ -573,6 +573,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Try(tree: Tree)(expr, cases, finalizer)
}
+ override def skipTransform(tree: Tree)(implicit ctx: Context) = tree.tpe.isError
+
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
def isValue(implicit ctx: Context): Boolean =
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala
index f3ffce8f8..99bc3240f 100644
--- a/compiler/src/dotty/tools/dotc/ast/untpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala
@@ -15,9 +15,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
// ----- Tree cases that exist in untyped form only ------------------
trait OpTree extends Tree {
- def op: Name
- override def isTerm = op.isTermName
- override def isType = op.isTypeName
+ def op: Ident
+ override def isTerm = op.name.isTermName
+ override def isType = op.name.isTypeName
}
/** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice
@@ -66,9 +66,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
*/
class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body)
- case class InfixOp(left: Tree, op: Name, right: Tree) extends OpTree
- case class PostfixOp(od: Tree, op: Name) extends OpTree
- case class PrefixOp(op: Name, od: Tree) extends OpTree
+ case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree
+ case class PostfixOp(od: Tree, op: Ident) extends OpTree
+ case class PrefixOp(op: Ident, od: Tree) extends OpTree
case class Parens(t: Tree) extends ProxyTree {
def forwardTo = t
}
@@ -357,7 +357,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
* parameter, the reference will be a repeated argument.
*/
def refOfDef(tree: MemberDef)(implicit ctx: Context) = tree match {
- case ValDef(_, PostfixOp(_, nme.raw.STAR), _) => repeated(Ident(tree.name))
+ case ValDef(_, PostfixOp(_, Ident(nme.raw.STAR)), _) => repeated(Ident(tree.name))
case _ => Ident(tree.name)
}
@@ -409,15 +409,15 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
case _ => untpd.Function(args, body).withPos(tree.pos)
}
- def InfixOp(tree: Tree)(left: Tree, op: Name, right: Tree) = tree match {
+ def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree) = tree match {
case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
case _ => untpd.InfixOp(left, op, right).withPos(tree.pos)
}
- def PostfixOp(tree: Tree)(od: Tree, op: Name) = tree match {
+ def PostfixOp(tree: Tree)(od: Tree, op: Ident) = tree match {
case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree
case _ => untpd.PostfixOp(od, op).withPos(tree.pos)
}
- def PrefixOp(tree: Tree)(op: Name, od: Tree) = tree match {
+ def PrefixOp(tree: Tree)(op: Ident, od: Tree) = tree match {
case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree
case _ => untpd.PrefixOp(op, od).withPos(tree.pos)
}
@@ -476,7 +476,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case SymbolLit(str) =>
cpy.SymbolLit(tree)(str)
case InterpolatedString(id, segments) =>
- cpy.InterpolatedString(tree)(id, transform(segments))
+ cpy.InterpolatedString(tree)(id, segments.map(transform(_)))
case Function(args, body) =>
cpy.Function(tree)(transform(args), transform(body))
case InfixOp(left, op, right) =>
diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
index 21a6c1165..e4c90789c 100644
--- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -101,6 +101,7 @@ class ScalaSettings extends Settings.SettingGroup {
val XoldPatmat = BooleanSetting("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.")
val XnoPatmatAnalysis = BooleanSetting("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
val XfullLubs = BooleanSetting("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")
+ val wikiSyntax = BooleanSetting("-Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc")
/** -Y "Private" settings
*/
@@ -212,11 +213,18 @@ class ScalaSettings extends Settings.SettingGroup {
"A directory containing static resources needed for the API documentation"
)
- val DocTitle = StringSetting (
- "-Ydoc-title",
- "title",
- "The overall name of the Scaladoc site",
- ""
+ val siteRoot = StringSetting(
+ "-siteroot",
+ "site root",
+ "A directory containing static files from which to generate documentation",
+ sys.props("user.dir")
+ )
+
+ val projectName = StringSetting (
+ "-project",
+ "project title",
+ "The name of the project",
+ sys.props("user.dir").split(sys.props("file.separator")).last
)
val DocVersion = StringSetting (
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 0aeb28d36..7fe6505ff 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -26,6 +26,9 @@ object Definitions {
* else without affecting the set of programs that can be compiled.
*/
val MaxImplementedFunctionArity = 22
+
+ /** The maximal arity of a function that can be accessed as member of a structural type */
+ val MaxStructuralMethodArity = 7
}
/** A class defining symbols and types of standard definitions
@@ -130,7 +133,7 @@ class Definitions {
ClassInfo(ScalaPackageClass.thisType, cls, ObjectType :: parentTraits, decls)
}
}
- newClassSymbol(ScalaPackageClass, name, Trait, completer)
+ newClassSymbol(ScalaPackageClass, name, Trait | NoInits, completer)
}
private def newMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
@@ -515,6 +518,7 @@ class Definitions {
lazy val LanguageModuleRef = ctx.requiredModule("scala.language")
def LanguageModuleClass(implicit ctx: Context) = LanguageModuleRef.symbol.moduleClass.asClass
lazy val NonLocalReturnControlType: TypeRef = ctx.requiredClassRef("scala.runtime.NonLocalReturnControl")
+ lazy val SelectableType: TypeRef = ctx.requiredClassRef("scala.Selectable")
lazy val ClassTagType = ctx.requiredClassRef("scala.reflect.ClassTag")
def ClassTagClass(implicit ctx: Context) = ClassTagType.symbol.asClass
@@ -766,6 +770,18 @@ class Definitions {
lazy val PhantomClasses = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
+ /** Classes that are known not to have an initializer irrespective of
+ * whether NoInits is set. Note: FunctionXXLClass is in this set
+ * because if it is compiled by Scala2, it does not get a NoInit flag.
+ * But since it is introduced only at erasure, there's no chance
+ * for augmentScala2Traits to do anything on a class that inherits it. So
+ * it also misses an implementation class, which means that the usual scheme
+ * of calling a superclass init in the implementation class of a Scala2
+ * trait gets screwed up. Therefore, it is mandatory that FunctionXXL
+ * is treated as a NoInit trait.
+ */
+ lazy val NoInitClasses = PhantomClasses + FunctionXXLClass
+
def isPolymorphicAfterErasure(sym: Symbol) =
(sym eq Any_isInstanceOf) || (sym eq Any_asInstanceOf)
diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala
index 6a53e1b30..44608296a 100644
--- a/compiler/src/dotty/tools/dotc/core/Phases.scala
+++ b/compiler/src/dotty/tools/dotc/core/Phases.scala
@@ -40,9 +40,6 @@ trait Phases {
def atPhaseNotLaterThan[T](limit: Phase)(op: Context => T): T =
if (!limit.exists || phase <= limit) op(this) else atPhase(limit)(op)
- def atPhaseNotLaterThanTyper[T](op: Context => T): T =
- atPhaseNotLaterThan(base.typerPhase)(op)
-
def isAfterTyper: Boolean = base.isAfterTyper(phase)
}
@@ -266,6 +263,13 @@ object Phases {
trait Phase extends DotClass {
+ /** A name given to the `Phase` that can be used to debug the compiler. For
+ * instance, it is possible to print trees after a given phase using:
+ *
+ * ```bash
+ * $ ./bin/dotc -Xprint:<phaseNameHere> sourceFile.scala
+ * ```
+ */
def phaseName: String
/** List of names of phases that should precede this phase */
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index 716959648..4a9c50dad 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -481,6 +481,7 @@ object StdNames {
val sameElements: N = "sameElements"
val scala_ : N = "scala"
val selectDynamic: N = "selectDynamic"
+ val selectDynamicMethod: N = "selectDynamicMethod"
val selectOverloadedMethod: N = "selectOverloadedMethod"
val selectTerm: N = "selectTerm"
val selectType: N = "selectType"
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 636204f64..ae9122853 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -41,9 +41,11 @@ object Types {
implicit def eqType: Eq[Type, Type] = Eq
- /** The class of types.
+ /** Main class representing types.
+ *
* The principal subclasses and sub-objects are as follows:
*
+ * ```none
* Type -+- ProxyType --+- NamedType ----+--- TypeRef
* | | \
* | +- SingletonType-+-+- TermRef
@@ -74,6 +76,7 @@ object Types {
* +- NoPrefix
* +- ErrorType
* +- WildcardType
+ * ```
*
* Note: please keep in sync with copy in `docs/docs/internals/type-system.md`.
*/
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 97a82e80d..5b751ef3c 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -818,7 +818,7 @@ class ClassfileParser(
case Some(entry) =>
val outerName = entry.outerName.stripModuleClassSuffix
val owner = classSymbol(outerName)
- val result = ctx.atPhaseNotLaterThanTyper { implicit ctx =>
+ val result = ctx.atPhaseNotLaterThan(ctx.typerPhase) { implicit ctx =>
getMember(owner, innerName.toTypeName)
}
assert(result ne NoSymbol,
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
index 0dc8d8fea..fb37c9e7d 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
@@ -31,8 +31,10 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
def nameRefToString(ref: NameRef): String = nameToString(tastyName(ref))
def printNames() =
- for ((name, idx) <- tastyName.contents.zipWithIndex)
- println(f"$idx%4d: " + nameToString(name))
+ for ((name, idx) <- tastyName.contents.zipWithIndex) {
+ val index = "%4d: ".format(idx)
+ println(index + nameToString(name))
+ }
def printContents(): Unit = {
println("Names:")
@@ -47,7 +49,10 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
def unpickle(reader: TastyReader, tastyName: TastyName.Table): Unit = {
import reader._
var indent = 0
- def newLine() = print(f"\n ${index(currentAddr) - index(startAddr)}%5d:" + " " * indent)
+ def newLine() = {
+ val length = "%5d:".format(index(currentAddr) - index(startAddr))
+ print(s"\n $length" + " " * indent)
+ }
def printNat() = print(" " + readNat())
def printName() = {
val idx = readNat()
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 51f08a295..ffd594454 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -733,11 +733,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
// no longer necessary.
goto(end)
setPos(start, tree)
-
- // This is also done in PostTyper but needs to be redone here
- if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
- sym.info = Checking.checkNoPrivateLeaks(sym, tree.pos)
- }
+ sym.info = ta.avoidPrivateLeaks(sym, tree.pos)
tree
}
diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
index 92ab10db9..d35594823 100644
--- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
@@ -448,7 +448,7 @@ object JavaParsers {
if (in.token == DOTDOTDOT) {
in.nextToken()
t = atPos(t.pos.start) {
- PostfixOp(t, nme.raw.STAR)
+ PostfixOp(t, Ident(nme.raw.STAR))
}
}
atPos(start, in.offset) {
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index a733eb65d..3162f61b4 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -30,7 +30,7 @@ object Parsers {
import reporting.diagnostic.Message
import reporting.diagnostic.messages._
- case class OpInfo(operand: Tree, operator: Name, offset: Offset)
+ case class OpInfo(operand: Tree, operator: Ident, offset: Offset)
class ParensCounters {
private var parCounts = new Array[Int](lastParen - firstParen)
@@ -414,18 +414,17 @@ object Parsers {
"left- and right-associative operators with same precedence may not be mixed", offset)
def reduceStack(base: List[OpInfo], top: Tree, prec: Int, leftAssoc: Boolean): Tree = {
- if (opStack != base && precedence(opStack.head.operator) == prec)
- checkAssoc(opStack.head.offset, opStack.head.operator, leftAssoc)
+ if (opStack != base && precedence(opStack.head.operator.name) == prec)
+ checkAssoc(opStack.head.offset, opStack.head.operator.name, leftAssoc)
def recur(top: Tree): Tree = {
if (opStack == base) top
else {
val opInfo = opStack.head
- val opPrec = precedence(opInfo.operator)
+ val opPrec = precedence(opInfo.operator.name)
if (prec < opPrec || leftAssoc && prec == opPrec) {
opStack = opStack.tail
recur {
- val opPos = Position(opInfo.offset, opInfo.offset + opInfo.operator.length, opInfo.offset)
- atPos(opPos union opInfo.operand.pos union top.pos) {
+ atPos(opInfo.operator.pos union opInfo.operand.pos union top.pos) {
InfixOp(opInfo.operand, opInfo.operator, top)
}
}
@@ -449,10 +448,9 @@ object Parsers {
val base = opStack
var top = first
while (isIdent && in.name != notAnOperator) {
- val op = if (isType) in.name.toTypeName else in.name
- top = reduceStack(base, top, precedence(op), isLeftAssoc(op))
+ val op = if (isType) typeIdent() else termIdent()
+ top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name))
opStack = OpInfo(top, op, in.offset) :: opStack
- ident()
newLineOptWhenFollowing(canStartOperand)
if (maybePostfix && !canStartOperand(in.token)) {
val topInfo = opStack.head
@@ -870,7 +868,7 @@ object Parsers {
val t = toplevelTyp()
if (isIdent(nme.raw.STAR)) {
in.nextToken()
- atPos(startOffset(t)) { PostfixOp(t, nme.raw.STAR) }
+ atPos(startOffset(t)) { PostfixOp(t, Ident(nme.raw.STAR)) }
} else t
}
@@ -1189,11 +1187,11 @@ object Parsers {
val prefixExpr = () =>
if (isIdent && nme.raw.isUnary(in.name)) {
val start = in.offset
- val name = ident()
- if (name == nme.raw.MINUS && isNumericLit)
+ val op = termIdent()
+ if (op.name == nme.raw.MINUS && isNumericLit)
simpleExprRest(literal(start), canApply = true)
else
- atPos(start) { PrefixOp(name, simpleExpr()) }
+ atPos(start) { PrefixOp(op, simpleExpr()) }
}
else simpleExpr()
@@ -1260,7 +1258,7 @@ object Parsers {
val app = atPos(startOffset(t), in.offset) { Apply(t, argumentExprs()) }
simpleExprRest(app, canApply = true)
case USCORE =>
- atPos(startOffset(t), in.skipToken()) { PostfixOp(t, nme.WILDCARD) }
+ atPos(startOffset(t), in.skipToken()) { PostfixOp(t, Ident(nme.WILDCARD)) }
case _ =>
t
}
diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 3085ad8fd..5b75df6b2 100644
--- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -61,7 +61,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
override def nameString(name: Name): String = name.decode.toString
override protected def simpleNameString(sym: Symbol): String = {
- val name = sym.originalName
+ val name = if (ctx.property(XprintMode).isEmpty) sym.originalName else sym.name
nameString(if (sym is ExpandedTypeParam) name.asTypeName.unexpandedName else name)
}
@@ -516,7 +516,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
argsText ~ " => " ~ toText(body)
}
case InfixOp(l, op, r) =>
- val opPrec = parsing.precedence(op)
+ val opPrec = parsing.precedence(op.name)
changePrec(opPrec) { toText(l) ~ " " ~ toText(op) ~ " " ~ toText(r) }
case PostfixOp(l, op) =>
changePrec(InfixPrec) { toText(l) ~ " " ~ toText(op) }
diff --git a/compiler/src/dotty/tools/dotc/printing/package.scala b/compiler/src/dotty/tools/dotc/printing/package.scala
index 814eb2ad0..e2c0dda1b 100644
--- a/compiler/src/dotty/tools/dotc/printing/package.scala
+++ b/compiler/src/dotty/tools/dotc/printing/package.scala
@@ -2,6 +2,7 @@ package dotty.tools.dotc
import core.StdNames.nme
import parsing.{precedence, minPrec, maxPrec, minInfixPrec}
+import util.Property.Key
package object printing {
@@ -14,4 +15,9 @@ package object printing {
val GlobalPrec = parsing.minPrec
val TopLevelPrec = parsing.minPrec - 1
+ /** A property to indicate whether the compiler is currently doing -Xprint
+ *
+ * -Xprint will print `sym.name` instead of `sym.originalName`
+ */
+ val XprintMode = new Key[Unit]
}
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index 71ecb5c65..00abddd91 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -542,7 +542,9 @@ object Erasure extends TypeTestsCasts{
* to deal with boxing and unboxing of value classes ourselves.
*/
override def typedClosure(tree: untpd.Closure, pt: Type)(implicit ctx: Context) = {
- val implClosure @ Closure(_, meth, _) = super.typedClosure(tree, pt)
+ val xxl = defn.isUnimplementedFunctionClass(tree.typeOpt.typeSymbol)
+ var implClosure @ Closure(_, meth, _) = super.typedClosure(tree, pt)
+ if (xxl) implClosure = cpy.Closure(implClosure)(tpt = TypeTree(defn.FunctionXXLType))
implClosure.tpe match {
case SAMType(sam) =>
val implType = meth.tpe.widen
diff --git a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
index 8bc4a2aa9..ebd2ae436 100644
--- a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
+++ b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
@@ -7,36 +7,37 @@ import core._
import Contexts.Context, Types._, Constants._, Decorators._, Symbols._
import TypeUtils._, TypeErasure._, Flags._
-
/** Implements partial evaluation of `sc.isInstanceOf[Sel]` according to:
*
- * +-------------+----------------------------+----------------------------+------------------+
* | Sel\sc | trait | class | final class |
- * +-------------+----------------------------+----------------------------+------------------+
+ * | ----------: | :------------------------: | :------------------------: | :--------------: |
* | trait | ? | ? | statically known |
* | class | ? | false if classes unrelated | statically known |
* | final class | false if classes unrelated | false if classes unrelated | statically known |
- * +-------------+----------------------------+----------------------------+------------------+
*
* This is a generalized solution to raising an error on unreachable match
* cases and warnings on other statically known results of `isInstanceOf`.
*
* Steps taken:
*
- * 1. evalTypeApply will establish the matrix and choose the appropriate
- * handling for the case:
- * 2. a) Sel/sc is a value class or scrutinee is `Any`
- * b) handleStaticallyKnown
- * c) falseIfUnrelated with `scrutinee <:< selector`
- * d) handleFalseUnrelated
- * e) leave as is (aka `happens`)
- * 3. Rewrite according to step taken in `2`
+ * 1. `evalTypeApply` will establish the matrix and choose the appropriate
+ * handling for the case:
+ * - Sel/sc is a value class or scrutinee is `Any`
+ * - `handleStaticallyKnown`
+ * - `falseIfUnrelated` with `scrutinee <:< selector`
+ * - `handleFalseUnrelated`
+ * - leave as is (`happens`)
+ * 2. Rewrite according to steps taken in 1
*/
class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
import dotty.tools.dotc.ast.tpd._
- def phaseName = "isInstanceOfEvaluator"
+ val phaseName = "isInstanceOfEvaluator"
+
+ /** Transforms a [TypeApply](dotty.tools.dotc.ast.Trees.TypeApply) in order to
+ * evaluate an `isInstanceOf` check according to the rules defined above.
+ */
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = {
val defn = ctx.definitions
diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
index 27cfc835a..fd4370d3e 100644
--- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
@@ -175,7 +175,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
case Some(call) =>
if (defn.PhantomClasses.contains(baseCls)) Nil else call :: Nil
case None =>
- if (baseCls.is(NoInitsTrait) || defn.PhantomClasses.contains(baseCls)) Nil
+ if (baseCls.is(NoInitsTrait) || defn.NoInitClasses.contains(baseCls)) Nil
else {
//println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 181dfccd9..7c49e68dd 100644
--- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -1077,8 +1077,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
trait MatchTranslator extends TreeMakers with ScalacPatternExpanders {
- def isBackquoted(x: Ident) = x.isInstanceOf[BackquotedIdent]
-
def isVarPattern(pat: Tree): Boolean = pat match {
case x: BackquotedIdent => false
case x: Ident => x.name.isVariableName
diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
index e7c0df1b9..8dff58dea 100644
--- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -107,12 +107,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
private def transformMemberDef(tree: MemberDef)(implicit ctx: Context): Unit = {
val sym = tree.symbol
sym.transformAnnotations(transformAnnot)
- // Has to be redone in TreeUnpickler
- if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
- val info1 = Checking.checkNoPrivateLeaks(sym, tree.pos)
- if (info1 ne sym.info)
- sym.copySymDenotation(info = info1).installAfter(thisTransformer)
- }
}
private def transformSelect(tree: Select, targs: List[Tree])(implicit ctx: Context): Tree = {
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index 321c275d7..ca62ed0a9 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -415,6 +415,8 @@ object Checking {
/** Verify classes extending AnyVal meet the requirements */
def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = {
def checkValueClassMember(stat: Tree) = stat match {
+ case _: TypeDef if stat.symbol.isClass =>
+ ctx.error(s"value class may not define an inner class", stat.pos)
case _: ValDef if !stat.symbol.is(ParamAccessor) =>
ctx.error(s"value class may not define non-parameter field", stat.pos)
case d: DefDef if d.symbol.isConstructor =>
diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
index 4039c8b81..000cfd026 100644
--- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
@@ -7,10 +7,13 @@ import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.core.Constants.Constant
import dotty.tools.dotc.core.Contexts.Context
-import dotty.tools.dotc.core.Names.Name
+import dotty.tools.dotc.core.Names.{Name, TermName}
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.Types._
import dotty.tools.dotc.core.Decorators._
+import core.Symbols._
+import core.Definitions
+import Inferencing._
import ErrorReporting._
object Dynamic {
@@ -18,7 +21,10 @@ object Dynamic {
name == nme.applyDynamic || name == nme.selectDynamic || name == nme.updateDynamic || name == nme.applyDynamicNamed
}
-/** Translates selection that does not typecheck according to the scala.Dynamic rules:
+/** Handles programmable member selections of `Dynamic` instances and values
+ * with structural types. Two functionalities:
+ *
+ * 1. Translates selection that does not typecheck according to the scala.Dynamic rules:
* foo.bar(baz) = quux ~~> foo.selectDynamic(bar).update(baz, quux)
* foo.bar = baz ~~> foo.updateDynamic("bar")(baz)
* foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
@@ -26,6 +32,10 @@ object Dynamic {
* foo.bar ~~> foo.selectDynamic(bar)
*
* The first matching rule of is applied.
+ *
+ * 2. Translates member selections on structural types to calls of `selectDynamic`
+ * or `selectDynamicMethod` on a `Selectable` instance. @See handleStructural.
+ *
*/
trait Dynamic { self: Typer with Applications =>
import Dynamic._
@@ -100,4 +110,56 @@ trait Dynamic { self: Typer with Applications =>
else untpd.TypeApply(select, targs)
untpd.Apply(selectWithTypes, Literal(Constant(name.toString)))
}
+
+ /** Handle reflection-based dispatch for members of structural types.
+ * Given `x.a`, where `x` is of (widened) type `T` and `x.a` is of type `U`:
+ *
+ * If `U` is a value type, map `x.a` to the equivalent of:
+ *
+ * (x: Selectable).selectDynamic(x, "a").asInstanceOf[U]
+ *
+ * If `U` is a method type (T1,...,Tn)R, map `x.a` to the equivalent of:
+ *
+ * (x: Selectable).selectDynamicMethod("a", CT1, ..., CTn).asInstanceOf[(T1,...,Tn) => R]
+ *
+ * where CT1,...,CTn are the class tags representing the erasure of T1,...,Tn.
+ *
+ * It's an error if U is neither a value nor a method type, or a dependent method
+ * type, or of too large arity (limit is Definitions.MaxStructuralMethodArity).
+ */
+ def handleStructural(tree: Tree)(implicit ctx: Context): Tree = {
+ val Select(qual, name) = tree
+
+ def structuralCall(selectorName: TermName, formals: List[Tree]) = {
+ val selectable = adapt(qual, defn.SelectableType)
+ val scall = untpd.Apply(
+ untpd.TypedSplice(selectable.select(selectorName)),
+ (Literal(Constant(name.toString)) :: formals).map(untpd.TypedSplice(_)))
+ typed(scall)
+ }
+
+ def fail(reason: String) =
+ errorTree(tree, em"Structural access not allowed on method $name because it $reason")
+
+ tree.tpe.widen match {
+ case tpe: MethodType =>
+ if (tpe.isDependent)
+ fail(i"has a dependent method type")
+ else if (tpe.paramNames.length > Definitions.MaxStructuralMethodArity)
+ fail(i"""takes too many parameters.
+ |Structural types only support methods taking up to ${Definitions.MaxStructuralMethodArity} arguments""")
+ else {
+ def issueError(msgFn: String => String): Unit = ctx.error(msgFn(""), tree.pos)
+ val ctags = tpe.paramTypes.map(pt =>
+ inferImplicitArg(defn.ClassTagType.appliedTo(pt :: Nil), issueError, tree.pos.endPos))
+ structuralCall(nme.selectDynamicMethod, ctags).asInstance(tpe.toFunctionType())
+ }
+ case tpe: ValueType =>
+ structuralCall(nme.selectDynamic, Nil).asInstance(tpe)
+ case tpe: PolyType =>
+ fail("is polymorphic")
+ case tpe =>
+ fail(i"has an unsupported type: $tpe")
+ }
+ }
}
diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
index c390ae808..e7e7ece78 100644
--- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -144,7 +144,7 @@ object EtaExpansion {
ids = ids.init :+ repeated(ids.last)
var body: Tree = Apply(lifted, ids)
mt.resultType match {
- case rt: MethodType if !rt.isImplicit => body = PostfixOp(body, nme.WILDCARD)
+ case rt: MethodType if !rt.isImplicit => body = PostfixOp(body, Ident(nme.WILDCARD))
case _ =>
}
val fn = untpd.Function(params, body)
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index f7d8556a7..6949221fb 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -69,9 +69,9 @@ object Implicits {
case mt: MethodType =>
mt.isImplicit ||
mt.paramTypes.length != 1 ||
- !(argType relaxed_<:< wildApprox(mt.paramTypes.head)(ctx.fresh.setExploreTyperState))
+ !(argType relaxed_<:< wildApprox(mt.paramTypes.head, null, Set.empty)(ctx.fresh.setExploreTyperState))
case rtp =>
- discardForView(wildApprox(rtp), argType)
+ discardForView(wildApprox(rtp, null, Set.empty), argType)
}
case tpw: TermRef =>
false // can't discard overloaded refs
@@ -664,7 +664,7 @@ trait Implicits { self: Typer =>
}
/** The expected type where parameters and uninstantiated typevars are replaced by wildcard types */
- val wildProto = implicitProto(pt, wildApprox(_))
+ val wildProto = implicitProto(pt, wildApprox(_, null, Set.empty))
/** Search failures; overridden in ExplainedImplicitSearch */
protected def nonMatchingImplicit(ref: TermRef, trail: List[MessageContainer]): SearchFailure = NoImplicitMatches
diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
index 09487570d..cfc0003c6 100644
--- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
@@ -327,7 +327,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
(tp.paramNames, tp.paramTypes, argss.head).zipped.foreach { (name, paramtp, arg) =>
def isByName = paramtp.dealias.isInstanceOf[ExprType]
paramBinding(name) = arg.tpe.stripAnnots.stripTypeVar match {
- case argtpe: SingletonType if isByName || isIdempotentExpr(arg) => argtpe
+ case argtpe: SingletonType if isIdempotentExpr(arg) => argtpe
case argtpe =>
val inlineFlag = if (paramtp.hasAnnotation(defn.InlineParamAnnot)) Inline else EmptyFlags
val (bindingFlags, bindingType) =
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala
index 068ef3e4b..3860ba225 100644
--- a/compiler/src/dotty/tools/dotc/typer/Namer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala
@@ -491,22 +491,26 @@ class Namer { typer: Typer =>
if (cdef.isClassDef) {
classDef(name) = cdef
cdef.attachmentOrElse(ExpandedTree, cdef) match {
- case Thicket(cls :: mval :: (mcls @ TypeDef(_, _: Template)) :: crest) =>
+ case Thicket(cls :: mval :: (mcls @ TypeDef(mname, _: Template)) :: crest)
+ if name.moduleClassName == mname =>
moduleDef(name) = mcls
case _ =>
}
}
for (mdef @ ModuleDef(name, _) <- stats if !mdef.mods.is(Flags.Package)) {
val typName = name.toTypeName
- val Thicket(vdef :: (mcls @ TypeDef(_, impl: Template)) :: Nil) = mdef.attachment(ExpandedTree)
+ // Expansion of object is a flattened thicket with the first two elements being:
+ // module val :: module class :: rest
+ val Thicket(vdef :: (mcls @ TypeDef(_, impl: Template)) :: rest) = expanded(mdef)
moduleDef(typName) = mcls
classDef get name.toTypeName match {
case Some(cdef) =>
cdef.attachmentOrElse(ExpandedTree, cdef) match {
- case Thicket(cls :: mval :: TypeDef(_, compimpl: Template) :: crest) =>
+ case Thicket(cls :: mval :: TypeDef(mname, compimpl: Template) :: crest)
+ if name.moduleClassName == mname =>
val mcls1 = cpy.TypeDef(mcls)(
rhs = cpy.Template(impl)(body = compimpl.body ++ impl.body))
- mdef.putAttachment(ExpandedTree, Thicket(vdef :: mcls1 :: Nil))
+ mdef.putAttachment(ExpandedTree, Thicket(vdef :: mcls1 :: rest))
moduleDef(typName) = mcls1
cdef.putAttachment(ExpandedTree, Thicket(cls :: crest))
case _ =>
@@ -668,13 +672,15 @@ class Namer { typer: Typer =>
* to pick up the context at the point where the completer was created.
*/
def completeInCreationContext(denot: SymDenotation): Unit = {
+ val sym = denot.symbol
original match {
- case original: MemberDef => addAnnotations(denot.symbol, original)
+ case original: MemberDef => addAnnotations(sym, original)
case _ =>
}
addInlineInfo(denot)
- denot.info = typeSig(denot.symbol)
- Checking.checkWellFormed(denot.symbol)
+ denot.info = typeSig(sym)
+ Checking.checkWellFormed(sym)
+ denot.info = avoidPrivateLeaks(sym, sym.pos)
}
}
@@ -854,6 +860,7 @@ class Namer { typer: Typer =>
if (isDerivedValueClass(cls)) cls.setFlag(Final)
cls.setApplicableFlags(
(NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat)))
+ cls.info = avoidPrivateLeaks(cls, cls.pos)
}
}
@@ -965,7 +972,7 @@ class Namer { typer: Typer =>
ctx.defContext(sym).denotNamed(original)
def paramProto(paramss: List[List[Type]], idx: Int): Type = paramss match {
case params :: paramss1 =>
- if (idx < params.length) wildApprox(params(idx))
+ if (idx < params.length) wildApprox(params(idx), null, Set.empty)
else paramProto(paramss1, idx - params.length)
case nil =>
WildcardType
diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index eb46a131f..d666b563e 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -437,65 +437,82 @@ object ProtoTypes {
/** Approximate occurrences of parameter types and uninstantiated typevars
* by wildcard types.
*/
- final def wildApprox(tp: Type, theMap: WildApproxMap = null)(implicit ctx: Context): Type = tp match {
+ final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[PolyParam])(implicit ctx: Context): Type = tp match {
case tp: NamedType => // default case, inlined for speed
if (tp.symbol.isStatic) tp
- else tp.derivedSelect(wildApprox(tp.prefix, theMap))
+ else tp.derivedSelect(wildApprox(tp.prefix, theMap, seen))
case tp: RefinedType => // default case, inlined for speed
- tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap))
+ tp.derivedRefinedType(
+ wildApprox(tp.parent, theMap, seen),
+ tp.refinedName,
+ wildApprox(tp.refinedInfo, theMap, seen))
case tp: TypeAlias => // default case, inlined for speed
- tp.derivedTypeAlias(wildApprox(tp.alias, theMap))
+ tp.derivedTypeAlias(wildApprox(tp.alias, theMap, seen))
case tp @ PolyParam(poly, pnum) =>
- def unconstrainedApprox = WildcardType(wildApprox(poly.paramBounds(pnum)).bounds)
- if (ctx.mode.is(Mode.TypevarsMissContext))
- unconstrainedApprox
- else
- ctx.typerState.constraint.entry(tp) match {
- case bounds: TypeBounds => wildApprox(WildcardType(bounds))
- case NoType => unconstrainedApprox
- case inst => wildApprox(inst)
- }
+ def wildApproxBounds(bounds: TypeBounds) =
+ if (bounds.lo.isInstanceOf[NamedType] && bounds.hi.isInstanceOf[NamedType])
+ WildcardType(wildApprox(bounds, theMap, seen).bounds)
+ else if (seen.contains(tp)) WildcardType
+ else WildcardType(wildApprox(bounds, theMap, seen + tp).bounds)
+ def unconstrainedApprox = wildApproxBounds(poly.paramBounds(pnum))
+ def approxPoly =
+ if (ctx.mode.is(Mode.TypevarsMissContext)) unconstrainedApprox
+ else
+ ctx.typerState.constraint.entry(tp) match {
+ case bounds: TypeBounds => wildApproxBounds(bounds)
+ case NoType => unconstrainedApprox
+ case inst => wildApprox(inst, theMap, seen)
+ }
+ approxPoly
case MethodParam(mt, pnum) =>
- WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum))))
+ WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap, seen)))
case tp: TypeVar =>
- wildApprox(tp.underlying)
+ wildApprox(tp.underlying, theMap, seen)
case tp @ HKApply(tycon, args) =>
- wildApprox(tycon) match {
+ wildApprox(tycon, theMap, seen) match {
case _: WildcardType => WildcardType // this ensures we get a * type
- case tycon1 => tp.derivedAppliedType(tycon1, args.mapConserve(wildApprox(_)))
+ case tycon1 => tp.derivedAppliedType(tycon1, args.mapConserve(wildApprox(_, theMap, seen)))
}
case tp: AndType =>
- val tp1a = wildApprox(tp.tp1)
- val tp2a = wildApprox(tp.tp2)
- def wildBounds(tp: Type) =
- if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
- if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
- WildcardType(wildBounds(tp1a) & wildBounds(tp2a))
- else
- tp.derivedAndType(tp1a, tp2a)
+ def approxAnd = {
+ val tp1a = wildApprox(tp.tp1, theMap, seen)
+ val tp2a = wildApprox(tp.tp2, theMap, seen)
+ def wildBounds(tp: Type) =
+ if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
+ if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
+ WildcardType(wildBounds(tp1a) & wildBounds(tp2a))
+ else
+ tp.derivedAndType(tp1a, tp2a)
+ }
+ approxAnd
case tp: OrType =>
- val tp1a = wildApprox(tp.tp1)
- val tp2a = wildApprox(tp.tp2)
- if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
- WildcardType(tp1a.bounds | tp2a.bounds)
- else
- tp.derivedOrType(tp1a, tp2a)
+ def approxOr = {
+ val tp1a = wildApprox(tp.tp1, theMap, seen)
+ val tp2a = wildApprox(tp.tp2, theMap, seen)
+ if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
+ WildcardType(tp1a.bounds | tp2a.bounds)
+ else
+ tp.derivedOrType(tp1a, tp2a)
+ }
+ approxOr
case tp: LazyRef =>
WildcardType
case tp: SelectionProto =>
- tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto), NoViewsAllowed)
+ tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto, theMap, seen), NoViewsAllowed)
case tp: ViewProto =>
- tp.derivedViewProto(wildApprox(tp.argType), wildApprox(tp.resultType))
+ tp.derivedViewProto(
+ wildApprox(tp.argType, theMap, seen),
+ wildApprox(tp.resultType, theMap, seen))
case _: ThisType | _: BoundType | NoPrefix => // default case, inlined for speed
tp
case _ =>
- (if (theMap != null) theMap else new WildApproxMap).mapOver(tp)
+ (if (theMap != null) theMap else new WildApproxMap(seen)).mapOver(tp)
}
@sharable object AssignProto extends UncachedGroundType with MatchAlways
- private[ProtoTypes] class WildApproxMap(implicit ctx: Context) extends TypeMap {
- def apply(tp: Type) = wildApprox(tp, this)
+ private[ProtoTypes] class WildApproxMap(val seen: Set[PolyParam])(implicit ctx: Context) extends TypeMap {
+ def apply(tp: Type) = wildApprox(tp, this, seen)
}
/** Dummy tree to be used as an argument of a FunProto or ViewProto type */
diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 5c07b7bcf..53ce5555b 100644
--- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -132,6 +132,11 @@ trait TypeAssigner {
def avoidingType(expr: Tree, bindings: List[Tree])(implicit ctx: Context): Type =
avoid(expr.tpe, localSyms(bindings).filter(_.isTerm))
+ def avoidPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type =
+ if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass)
+ Checking.checkNoPrivateLeaks(sym, pos)
+ else sym.info
+
def seqToRepeated(tree: Tree)(implicit ctx: Context): Tree =
Typed(tree, TypeTree(tree.tpe.widen.translateParameterized(defn.SeqClass, defn.RepeatedParamClass)))
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 22a4221ba..652c89094 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -1040,9 +1040,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
typr.println(s"adding refinement $refinement")
checkRefinementNonCyclic(refinement, refineCls, seen)
val rsym = refinement.symbol
- if (rsym.is(Method) && rsym.allOverriddenSymbols.isEmpty)
- ctx.error(i"refinement $rsym without matching type in parent $tpt1", refinement.pos)
- }
+ if (rsym.info.isInstanceOf[PolyType] && rsym.allOverriddenSymbols.isEmpty)
+ ctx.error(i"polymorphic refinement $rsym without matching type in parent $tpt1 is no longer allowed", refinement.pos) }
assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls)
}
@@ -1441,7 +1440,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(implicit ctx: Context): Tree = {
- val untpd.PostfixOp(qual, nme.WILDCARD) = tree
+ val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree
val pt1 = if (defn.isFunctionType(pt)) pt else AnyFunctionProto
var res = typed(qual, pt1)
if (pt1.eq(AnyFunctionProto) && !defn.isFunctionClass(res.tpe.classSymbol)) {
@@ -1542,7 +1541,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case tree: untpd.Annotated => typedAnnotated(tree, pt)
case tree: untpd.TypedSplice => typedTypedSplice(tree)
case tree: untpd.UnApply => typedUnApply(tree, pt)
- case tree @ untpd.PostfixOp(qual, nme.WILDCARD) => typedAsFunction(tree, pt)
+ case tree @ untpd.PostfixOp(qual, Ident(nme.WILDCARD)) => typedAsFunction(tree, pt)
case untpd.EmptyTree => tpd.EmptyTree
case _ => typedUnadapted(desugar(tree), pt)
}
@@ -2068,7 +2067,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
adaptInterpolated(tree.appliedToTypeTrees(typeArgs), pt, original))
}
case wtp =>
- pt match {
+ if (isStructuralTermSelect(tree)) adapt(handleStructural(tree), pt)
+ else pt match {
case pt: FunProto =>
adaptToArgs(wtp, pt)
case pt: PolyProto =>
diff --git a/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala b/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala
new file mode 100644
index 000000000..9e7402968
--- /dev/null
+++ b/compiler/test/dotty/tools/dotc/ast/UntypedTreeMapTest.scala
@@ -0,0 +1,32 @@
+package dotty.tools
+package dotc
+package ast
+
+import org.junit.Test
+import org.junit.Assert._
+
+import dotc.core.Contexts._
+import dotc.parsing.Parsers.Parser
+import dotc.util.SourceFile
+
+class UntpdTreeMapTest extends DottyTest {
+
+ import untpd._
+
+ def parse(code: String): Tree = {
+ val (_, stats) = new Parser(new SourceFile("<meta>", code.toCharArray)).templateStatSeq()
+ stats match { case List(stat) => stat; case stats => untpd.Thicket(stats) }
+ }
+
+ @Test
+ def testMapInterpolatedString = {
+ val tree = parse(""" q"hello ${2017}!" """)
+ val identity = new UntypedTreeMap {
+ override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
+ case _ => super.transform(tree)
+ }
+ }
+
+ assertEquals(tree.toString, identity.transform(tree).toString)
+ }
+}
diff --git a/doc-tool/resources/_includes/header.html b/doc-tool/resources/_includes/header.html
new file mode 100644
index 000000000..219cdf7f9
--- /dev/null
+++ b/doc-tool/resources/_includes/header.html
@@ -0,0 +1 @@
+<h1>Some header</h1>
diff --git a/doc-tool/resources/_includes/scala-logo.svg b/doc-tool/resources/_includes/scala-logo.svg
new file mode 100644
index 000000000..88268ccbe
--- /dev/null
+++ b/doc-tool/resources/_includes/scala-logo.svg
@@ -0,0 +1,30 @@
+<svg width="64px" height="109px" viewBox="0 0 64 109" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="logo-background" transform="translate(0.000000, 16.000000)" fill="#636363">
+ <path d="M0.5,59.5 C0.5,59.5 63.4,65.8 63.4,76.3 L63.4,51.1 C63.4,51.1 63.4,40.6 0.5,34.3 L0.5,59.5 L0.5,59.5 Z" id="logo-background-bottom"></path>
+ <path d="M0.5,25.9 C0.5,25.9 63.4,32.2 63.4,42.7 L63.4,17.5 C63.4,17.5 63.4,7 0.5,0.7 L0.5,10.5 L0.5,25.9 L0.5,25.9 Z" id="logo-background-top"></path>
+ </g>
+ <g id="logo-foreground" fill="#B6B6B6">
+ <path d="M0.5,109 L0.5,83.8 C0.5,83.8 63.4,77.5 63.4,67 L63.4,92.2 C63.5,92.3 63.5,102.7 0.5,109" id="Logo_Foreground_Bottom"></path>
+ <path d="M0.5,50.3 C0.5,50.3 63.4,44 63.4,33.5 L63.4,58.7 C63.4,58.7 63.4,69.2 0.5,75.5 L0.5,50.3 L0.5,50.3 Z" id="Logo_Foreground_Middle"></path>
+ <path d="M63.5,0 L63.5,25.2 C63.5,25.2 63.5,35.7 0.6,42 L0.6,16.7 C0.5,16.7 63.5,10.5 63.5,0" id="logo-foreground-top"></path>
+ </g>
+ <g id="dots" transform="translate(4.000000, 10.000000)" fill="#FFFFFF">
+ <g id="bottom" transform="translate(0.000000, 67.500000)">
+ <path d="M1.4471104,12.2885536 C1.45019313,12.2881864 1.45019313,12.2881864 1.45327704,12.2878189 C1.91768952,12.2324787 2.24930811,11.8111359 2.1939679,11.3467234 C2.13862768,10.8823109 1.71728488,10.5506923 1.2528724,10.6060325 C1.24980572,10.606398 1.24980572,10.606398 1.24674021,10.6067632 C0.782326598,10.6620939 0.450699376,11.0834299 0.506030077,11.5478435 C0.561360778,12.0122571 0.982696791,12.3438844 1.4471104,12.2885536 L1.4471104,12.2885536 Z M9.34858965,12.1304907 C9.35409106,12.129756 9.35409106,12.129756 9.35959333,12.129021 C10.1807278,12.019341 10.7574756,11.2647668 10.6477955,10.4436323 C10.5381155,9.62249789 9.78354128,9.04575011 8.96240683,9.15543014 C8.95693539,9.15616095 8.95693539,9.15616095 8.95146479,9.15689157 C8.13032806,9.26655457 7.55356464,10.0211168 7.66322765,10.8422536 C7.77289065,11.6633903 8.52745292,12.2401537 9.34858965,12.1304907 L9.34858965,12.1304907 Z M17.0066591,11.0493128 C17.0121188,11.0484984 17.0121188,11.0484984 17.0175789,11.0476838 C17.8369369,10.9254384 18.4020584,10.1621181 18.279813,9.34276003 C18.1575677,8.52340201 17.3942473,7.95828052 16.5748893,8.08052587 C16.5694641,8.08133528 16.5694641,8.08133528 16.5640392,8.08214454 C15.7446783,8.20437064 15.1795389,8.96767771 15.301765,9.78703861 C15.4239911,10.6063995 16.1872982,11.1715389 17.0066591,11.0493128 L17.0066591,11.0493128 Z M24.8225082,10.4232459 C24.8297684,10.4220275 24.8297684,10.4220275 24.8370287,10.420809 C25.922252,10.2386672 26.6543441,9.21126476 26.4722023,8.12604147 C26.2900605,7.04081818 25.2626581,6.30872601 24.1774348,6.49086783 C24.1702314,6.4920768 24.1702314,6.4920768 24.1630282,6.49328559 C23.0777996,6.67539597 22.3456777,7.70277717 22.5277881,8.78800574 C22.7098984,9.87323431 23.7372796,10.6053563 24.8225082,10.4232459 L24.8225082,10.4232459 Z M32.4725265,9.05261002 C33.5532108,8.84532993 34.2612448,7.80122849 34.0539647,6.72054419 C33.8466846,5.63985989 32.8025831,4.93182589 31.7218988,5.13910599 C31.714724,5.14048211 31.714724,5.14048211 31.7075489,5.14185807 C30.6268567,5.34909665 29.9187826,6.39317088 30.1260211,7.47386314 C30.3332597,8.5545554 31.3773339,9.26262952 32.4580262,9.05539095 C32.4652764,9.05400057 32.4652764,9.05400057 32.4725265,9.05261002 Z M39.8723866,6.89476879 C39.877909,6.8935242 39.877909,6.8935242 39.883431,6.89227947 C40.6915794,6.71010471 41.1990314,5.90728916 41.0168566,5.09914075 C40.8346818,4.29099233 40.0318663,3.78354042 39.2237179,3.96571517 C39.218279,3.96694116 39.218279,3.96694116 39.2128397,3.96816703 C38.404681,4.15029588 37.8971834,4.9530826 38.0793123,5.76124136 C38.2614411,6.56940012 39.0642279,7.07689764 39.8723866,6.89476879 L39.8723866,6.89476879 Z M47.4276119,5.00828445 C47.4329844,5.00678549 47.4329844,5.00678549 47.4383562,5.00528637 C48.2362896,4.78258973 48.7026111,3.95520561 48.4799145,3.15727221 C48.2572179,2.35933881 47.4298337,1.89301728 46.6319003,2.11571391 C46.6266645,2.1171751 46.6266645,2.1171751 46.6214279,2.11863616 C45.8234736,2.34125773 45.3570742,3.16859798 45.5796958,3.96655233 C45.8023173,4.76450667 46.6296576,5.23090603 47.4276119,5.00828445 L47.4276119,5.00828445 Z M54.419759,2.30643871 C54.8556933,2.13695884 55.0716973,1.6461737 54.9022174,1.21023941 C54.7327376,0.774305114 54.2419524,0.558301127 53.8060181,0.727780997 C53.8032127,0.728871549 53.8032127,0.728871549 53.8004064,0.729962021 C53.3644359,0.89934874 53.148327,1.39008772 53.3177137,1.82605822 C53.4871005,2.26202871 53.9778394,2.47813756 54.4138099,2.30875084 C54.4167849,2.30759485 54.4167849,2.30759485 54.419759,2.30643871 Z" id="Shape"></path>
+ <path d="M1.67760355,20.096503 C1.68306395,20.0958524 1.68306395,20.0958524 1.68852642,20.0952015 C2.51113381,19.9971782 3.09852524,19.2508595 3.00050189,18.4282521 C2.90247854,17.6056447 2.15615986,17.0182533 1.33355246,17.1162767 C1.3281205,17.1169239 1.3281205,17.1169239 1.3226906,17.1175709 C0.500081196,17.2155774 -0.0873255124,17.961884 0.0106809923,18.7844934 C0.108687497,19.6071028 0.854994145,20.1945095 1.67760355,20.096503 L1.67760355,20.096503 Z M9.34858965,19.1274206 C9.35409106,19.1266859 9.35409106,19.1266859 9.35959333,19.1259509 C10.1807278,19.0162709 10.7574756,18.2616967 10.6477955,17.4405622 C10.5381155,16.6194278 9.78354128,16.04268 8.96240683,16.15236 C8.95693539,16.1530908 8.95693539,16.1530908 8.95146479,16.1538215 C8.13032806,16.2634845 7.55356464,17.0180467 7.66322765,17.8391835 C7.77289065,18.6603202 8.52745292,19.2370836 9.34858965,19.1274206 L9.34858965,19.1274206 Z M17.1767435,18.6256231 C17.1839958,18.6245412 17.1839958,18.6245412 17.1912486,18.6234592 C18.27963,18.4610765 19.0303002,17.4471319 18.8679175,16.3587506 C18.7055348,15.2703693 17.6915903,14.519699 16.6032089,14.6820817 C16.5960024,14.6831569 16.5960024,14.6831569 16.5887964,14.6842319 C15.5004112,14.846589 14.7497172,15.8605159 14.9120743,16.948901 C15.0744314,18.0372862 16.0883584,18.7879802 17.1767435,18.6256231 L17.1767435,18.6256231 Z M24.8370287,17.4177379 C25.922252,17.2355961 26.6543441,16.2081937 26.4722023,15.1229704 C26.2900605,14.0377471 25.2626581,13.3056549 24.1774348,13.4877968 C24.1702314,13.4890057 24.1702314,13.4890057 24.1630282,13.4902145 C23.0777996,13.6723249 22.3456777,14.6997061 22.5277881,15.7849347 C22.7098984,16.8701632 23.7372796,17.6022852 24.8225082,17.4201748 C24.8297684,17.4189565 24.8297684,17.4189565 24.8370287,17.4177379 Z M32.4725265,16.061085 C33.5532108,15.853199 34.2612448,14.8060455 34.0539647,13.7222022 C33.8466846,12.6383589 32.8025831,11.9282552 31.7218988,12.1361412 C31.714724,12.1375214 31.714724,12.1375214 31.7075489,12.1389013 C30.6268567,12.3467457 29.9187826,13.3938719 30.1260211,14.4777232 C30.3332597,15.5615745 31.3773339,16.2717185 32.4580262,16.0638741 C32.4652764,16.0624797 32.4652764,16.0624797 32.4725265,16.061085 Z M40.0707225,14.4695476 C40.0780573,14.4678946 40.0780573,14.4678946 40.0853916,14.4662413 C41.158768,14.2242783 41.8327617,13.1579849 41.5907986,12.0846085 C41.3488355,11.011232 40.2825422,10.3372384 39.2091657,10.5792015 C39.2019419,10.5808298 39.2019419,10.5808298 39.1947175,10.582458 C38.1213273,10.8243601 37.447273,11.8906152 37.6891752,12.9640053 C37.9310773,14.0373955 38.9973324,14.7114498 40.0707225,14.4695476 L40.0707225,14.4695476 Z M47.4276119,12.0082845 C47.4329844,12.0067855 47.4329844,12.0067855 47.4383562,12.0052864 C48.2362896,11.7825897 48.7026111,10.9552056 48.4799145,10.1572722 C48.2572179,9.35933881 47.4298337,8.89301728 46.6319003,9.11571391 C46.6266645,9.1171751 46.6266645,9.1171751 46.6214279,9.11863616 C45.8234736,9.34125773 45.3570742,10.168598 45.5796958,10.9665523 C45.8023173,11.7645067 46.6296576,12.230906 47.4276119,12.0082845 L47.4276119,12.0082845 Z M54.8999721,9.57562965 C54.9052414,9.57358217 54.9052414,9.57358217 54.9105092,9.57153441 C55.6826371,9.27135123 56.0652239,8.40207131 55.7650408,7.62994336 C55.4648576,6.85781542 54.5955777,6.4752286 53.8234497,6.77541179 C53.8184808,6.77734338 53.8184808,6.77734338 53.8135101,6.77927482 C53.0413181,7.07929302 52.6585455,7.94849117 52.9585637,8.72068323 C53.2585819,9.4928753 54.12778,9.87564785 54.8999721,9.57562965 L54.8999721,9.57562965 Z" id="Shape"></path>
+ <path d="M1.45327704,26.6978168 C1.54647464,26.6867112 1.63432439,26.660866 1.7147722,26.6228911 C2.03520341,26.4716332 2.23820252,26.1279362 2.1939679,25.7567213 C2.13862768,25.2923089 1.71728488,24.9606903 1.2528724,25.0160305 C1.24980572,25.0163959 1.24980572,25.0163959 1.24674021,25.0167611 C0.782326598,25.0720918 0.450699376,25.4934278 0.506030077,25.9578415 C0.561360778,26.4222551 0.982696791,26.7538823 1.4471104,26.6985516 C1.45019313,26.6981843 1.45019313,26.6981843 1.45327704,26.6978168 Z M9.34858965,26.1274206 C9.35409106,26.1266859 9.35409106,26.1266859 9.35959333,26.1259509 C10.1807278,26.0162709 10.7574756,25.2616967 10.6477955,24.4405622 C10.5381155,23.6194278 9.78354128,23.04268 8.96240683,23.15236 C8.95693539,23.1530908 8.95693539,23.1530908 8.95146479,23.1538215 C8.13032806,23.2634845 7.55356464,24.0180467 7.66322765,24.8391835 C7.77289065,25.6603202 8.52745292,26.2370836 9.34858965,26.1274206 L9.34858965,26.1274206 Z M17.0066591,25.0462427 C17.0121188,25.0454283 17.0121188,25.0454283 17.0175789,25.0446136 C17.8369369,24.9223683 18.4020584,24.1590479 18.279813,23.3396899 C18.1575677,22.5203319 17.3942473,21.9552104 16.5748893,22.0774558 C16.5694641,22.0782652 16.5694641,22.0782652 16.5640392,22.0790744 C15.7446783,22.2013005 15.1795389,22.9646076 15.301765,23.7839685 C15.4239911,24.6033294 16.1872982,25.1684688 17.0066591,25.0462427 L17.0066591,25.0462427 Z M24.8225082,24.4201748 C24.8297684,24.4189565 24.8297684,24.4189565 24.8370287,24.4177379 C25.922252,24.2355961 26.6543441,23.2081937 26.4722023,22.1229704 C26.2900605,21.0377471 25.2626581,20.3056549 24.1774348,20.4877968 C24.1702314,20.4890057 24.1702314,20.4890057 24.1630282,20.4902145 C23.0777996,20.6723249 22.3456777,21.6997061 22.5277881,22.7849347 C22.7098984,23.8701632 23.7372796,24.6022852 24.8225082,24.4201748 L24.8225082,24.4201748 Z M32.4725265,23.0495399 C33.5532108,22.8422598 34.2612448,21.7981584 34.0539647,20.7174741 C33.8466846,19.6367898 32.8025831,18.9287558 31.7218988,19.1360359 C31.714724,19.137412 31.714724,19.137412 31.7075489,19.138788 C30.6268567,19.3460265 29.9187826,20.3901008 30.1260211,21.470793 C30.3332597,22.5514853 31.3773339,23.2595594 32.4580262,23.0523208 C32.4652764,23.0509305 32.4652764,23.0509305 32.4725265,23.0495399 Z M39.8723866,20.8947688 C39.877909,20.8935242 39.877909,20.8935242 39.883431,20.8922795 C40.6915794,20.7101047 41.1990314,19.9072892 41.0168566,19.0991407 C40.8346818,18.2909923 40.0318663,17.7835404 39.2237179,17.9657152 C39.218279,17.9669412 39.218279,17.9669412 39.2128397,17.968167 C38.404681,18.1502959 37.8971834,18.9530826 38.0793123,19.7612414 C38.2614411,20.5694001 39.0642279,21.0768976 39.8723866,20.8947688 L39.8723866,20.8947688 Z M47.4276119,19.0082845 C47.4329844,19.0067855 47.4329844,19.0067855 47.4383562,19.0052864 C48.2362896,18.7825897 48.7026111,17.9552056 48.4799145,17.1572722 C48.2572179,16.3593388 47.4298337,15.8930173 46.6319003,16.1157139 C46.6266645,16.1171751 46.6266645,16.1171751 46.6214279,16.1186362 C45.8234736,16.3412577 45.3570742,17.168598 45.5796958,17.9665523 C45.8023173,18.7645067 46.6296576,19.230906 47.4276119,19.0082845 L47.4276119,19.0082845 Z M54.4138099,15.7087505 C54.4167849,15.7075945 54.4167849,15.7075945 54.419759,15.7064383 C54.8556933,15.5369585 55.0716973,15.0461733 54.9022174,14.610239 C54.7327376,14.1743047 54.2419524,13.9583007 53.8060181,14.1277806 C53.8032127,14.1288712 53.8032127,14.1288712 53.8004064,14.1299616 C53.3644359,14.2993484 53.148327,14.7900873 53.3177137,15.2260578 C53.4871005,15.6620283 53.9778394,15.8781372 54.4138099,15.7087505 L54.4138099,15.7087505 Z" id="Shape"></path>
+ </g>
+ <g id="middle" transform="translate(0.000000, 33.900002)">
+ <path d="M1.4471104,12.2885536 C1.45019313,12.2881864 1.45019313,12.2881864 1.45327704,12.2878189 C1.91768952,12.2324787 2.24930811,11.8111359 2.1939679,11.3467234 C2.13862768,10.8823109 1.71728488,10.5506923 1.2528724,10.6060325 C1.24980572,10.606398 1.24980572,10.606398 1.24674021,10.6067632 C0.782326598,10.6620939 0.450699376,11.0834299 0.506030077,11.5478435 C0.561360778,12.0122571 0.982696791,12.3438844 1.4471104,12.2885536 L1.4471104,12.2885536 Z M9.34858965,12.1304907 C9.35409106,12.129756 9.35409106,12.129756 9.35959333,12.129021 C10.1807278,12.019341 10.7574756,11.2647668 10.6477955,10.4436323 C10.5381155,9.62249789 9.78354128,9.04575011 8.96240683,9.15543014 C8.95693539,9.15616095 8.95693539,9.15616095 8.95146479,9.15689157 C8.13032806,9.26655457 7.55356464,10.0211168 7.66322765,10.8422536 C7.77289065,11.6633903 8.52745292,12.2401537 9.34858965,12.1304907 L9.34858965,12.1304907 Z M17.0066591,11.0493128 C17.0121188,11.0484984 17.0121188,11.0484984 17.0175789,11.0476838 C17.8369369,10.9254384 18.4020584,10.1621181 18.279813,9.34276003 C18.1575677,8.52340201 17.3942473,7.95828052 16.5748893,8.08052587 C16.5694641,8.08133528 16.5694641,8.08133528 16.5640392,8.08214454 C15.7446783,8.20437064 15.1795389,8.96767771 15.301765,9.78703861 C15.4239911,10.6063995 16.1872982,11.1715389 17.0066591,11.0493128 L17.0066591,11.0493128 Z M24.8225082,10.4232459 C24.8297684,10.4220275 24.8297684,10.4220275 24.8370287,10.420809 C25.922252,10.2386672 26.6543441,9.21126476 26.4722023,8.12604147 C26.2900605,7.04081818 25.2626581,6.30872601 24.1774348,6.49086783 C24.1702314,6.4920768 24.1702314,6.4920768 24.1630282,6.49328559 C23.0777996,6.67539597 22.3456777,7.70277717 22.5277881,8.78800574 C22.7098984,9.87323431 23.7372796,10.6053563 24.8225082,10.4232459 L24.8225082,10.4232459 Z M32.4725265,9.05261002 C33.5532108,8.84532993 34.2612448,7.80122849 34.0539647,6.72054419 C33.8466846,5.63985989 32.8025831,4.93182589 31.7218988,5.13910599 C31.714724,5.14048211 31.714724,5.14048211 31.7075489,5.14185807 C30.6268567,5.34909665 29.9187826,6.39317088 30.1260211,7.47386314 C30.3332597,8.5545554 31.3773339,9.26262952 32.4580262,9.05539095 C32.4652764,9.05400057 32.4652764,9.05400057 32.4725265,9.05261002 Z M39.8723866,6.89476879 C39.877909,6.8935242 39.877909,6.8935242 39.883431,6.89227947 C40.6915794,6.71010471 41.1990314,5.90728916 41.0168566,5.09914075 C40.8346818,4.29099233 40.0318663,3.78354042 39.2237179,3.96571517 C39.218279,3.96694116 39.218279,3.96694116 39.2128397,3.96816703 C38.404681,4.15029588 37.8971834,4.9530826 38.0793123,5.76124136 C38.2614411,6.56940012 39.0642279,7.07689764 39.8723866,6.89476879 L39.8723866,6.89476879 Z M47.4276119,5.00828445 C47.4329844,5.00678549 47.4329844,5.00678549 47.4383562,5.00528637 C48.2362896,4.78258973 48.7026111,3.95520561 48.4799145,3.15727221 C48.2572179,2.35933881 47.4298337,1.89301728 46.6319003,2.11571391 C46.6266645,2.1171751 46.6266645,2.1171751 46.6214279,2.11863616 C45.8234736,2.34125773 45.3570742,3.16859798 45.5796958,3.96655233 C45.8023173,4.76450667 46.6296576,5.23090603 47.4276119,5.00828445 L47.4276119,5.00828445 Z M54.419759,2.30643871 C54.8556933,2.13695884 55.0716973,1.6461737 54.9022174,1.21023941 C54.7327376,0.774305114 54.2419524,0.558301127 53.8060181,0.727780997 C53.8032127,0.728871549 53.8032127,0.728871549 53.8004064,0.729962021 C53.3644359,0.89934874 53.148327,1.39008772 53.3177137,1.82605822 C53.4871005,2.26202871 53.9778394,2.47813756 54.4138099,2.30875084 C54.4167849,2.30759485 54.4167849,2.30759485 54.419759,2.30643871 Z" id="Shape"></path>
+ <path d="M1.67760355,20.096503 C1.68306395,20.0958524 1.68306395,20.0958524 1.68852642,20.0952015 C2.51113381,19.9971782 3.09852524,19.2508595 3.00050189,18.4282521 C2.90247854,17.6056447 2.15615986,17.0182533 1.33355246,17.1162767 C1.3281205,17.1169239 1.3281205,17.1169239 1.3226906,17.1175709 C0.500081196,17.2155774 -0.0873255124,17.961884 0.0106809923,18.7844934 C0.108687497,19.6071028 0.854994145,20.1945095 1.67760355,20.096503 L1.67760355,20.096503 Z M9.34858965,19.1274206 C9.35409106,19.1266859 9.35409106,19.1266859 9.35959333,19.1259509 C10.1807278,19.0162709 10.7574756,18.2616967 10.6477955,17.4405622 C10.5381155,16.6194278 9.78354128,16.04268 8.96240683,16.15236 C8.95693539,16.1530908 8.95693539,16.1530908 8.95146479,16.1538215 C8.13032806,16.2634845 7.55356464,17.0180467 7.66322765,17.8391835 C7.77289065,18.6603202 8.52745292,19.2370836 9.34858965,19.1274206 L9.34858965,19.1274206 Z M17.1767435,18.6256231 C17.1839958,18.6245412 17.1839958,18.6245412 17.1912486,18.6234592 C18.27963,18.4610765 19.0303002,17.4471319 18.8679175,16.3587506 C18.7055348,15.2703693 17.6915903,14.519699 16.6032089,14.6820817 C16.5960024,14.6831569 16.5960024,14.6831569 16.5887964,14.6842319 C15.5004112,14.846589 14.7497172,15.8605159 14.9120743,16.948901 C15.0744314,18.0372862 16.0883584,18.7879802 17.1767435,18.6256231 L17.1767435,18.6256231 Z M24.8370287,17.4177379 C25.922252,17.2355961 26.6543441,16.2081937 26.4722023,15.1229704 C26.2900605,14.0377471 25.2626581,13.3056549 24.1774348,13.4877968 C24.1702314,13.4890057 24.1702314,13.4890057 24.1630282,13.4902145 C23.0777996,13.6723249 22.3456777,14.6997061 22.5277881,15.7849347 C22.7098984,16.8701632 23.7372796,17.6022852 24.8225082,17.4201748 C24.8297684,17.4189565 24.8297684,17.4189565 24.8370287,17.4177379 Z M32.4725265,16.061085 C33.5532108,15.853199 34.2612448,14.8060455 34.0539647,13.7222022 C33.8466846,12.6383589 32.8025831,11.9282552 31.7218988,12.1361412 C31.714724,12.1375214 31.714724,12.1375214 31.7075489,12.1389013 C30.6268567,12.3467457 29.9187826,13.3938719 30.1260211,14.4777232 C30.3332597,15.5615745 31.3773339,16.2717185 32.4580262,16.0638741 C32.4652764,16.0624797 32.4652764,16.0624797 32.4725265,16.061085 Z M40.0707225,14.4695476 C40.0780573,14.4678946 40.0780573,14.4678946 40.0853916,14.4662413 C41.158768,14.2242783 41.8327617,13.1579849 41.5907986,12.0846085 C41.3488355,11.011232 40.2825422,10.3372384 39.2091657,10.5792015 C39.2019419,10.5808298 39.2019419,10.5808298 39.1947175,10.582458 C38.1213273,10.8243601 37.447273,11.8906152 37.6891752,12.9640053 C37.9310773,14.0373955 38.9973324,14.7114498 40.0707225,14.4695476 L40.0707225,14.4695476 Z M47.4276119,12.0082845 C47.4329844,12.0067855 47.4329844,12.0067855 47.4383562,12.0052864 C48.2362896,11.7825897 48.7026111,10.9552056 48.4799145,10.1572722 C48.2572179,9.35933881 47.4298337,8.89301728 46.6319003,9.11571391 C46.6266645,9.1171751 46.6266645,9.1171751 46.6214279,9.11863616 C45.8234736,9.34125773 45.3570742,10.168598 45.5796958,10.9665523 C45.8023173,11.7645067 46.6296576,12.230906 47.4276119,12.0082845 L47.4276119,12.0082845 Z M54.8999721,9.57562965 C54.9052414,9.57358217 54.9052414,9.57358217 54.9105092,9.57153441 C55.6826371,9.27135123 56.0652239,8.40207131 55.7650408,7.62994336 C55.4648576,6.85781542 54.5955777,6.4752286 53.8234497,6.77541179 C53.8184808,6.77734338 53.8184808,6.77734338 53.8135101,6.77927482 C53.0413181,7.07929302 52.6585455,7.94849117 52.9585637,8.72068323 C53.2585819,9.4928753 54.12778,9.87564785 54.8999721,9.57562965 L54.8999721,9.57562965 Z" id="Shape"></path>
+ <path d="M1.45327704,26.6978168 C1.54647464,26.6867112 1.63432439,26.660866 1.7147722,26.6228911 C2.03520341,26.4716332 2.23820252,26.1279362 2.1939679,25.7567213 C2.13862768,25.2923089 1.71728488,24.9606903 1.2528724,25.0160305 C1.24980572,25.0163959 1.24980572,25.0163959 1.24674021,25.0167611 C0.782326598,25.0720918 0.450699376,25.4934278 0.506030077,25.9578415 C0.561360778,26.4222551 0.982696791,26.7538823 1.4471104,26.6985516 C1.45019313,26.6981843 1.45019313,26.6981843 1.45327704,26.6978168 Z M9.34858965,26.1274206 C9.35409106,26.1266859 9.35409106,26.1266859 9.35959333,26.1259509 C10.1807278,26.0162709 10.7574756,25.2616967 10.6477955,24.4405622 C10.5381155,23.6194278 9.78354128,23.04268 8.96240683,23.15236 C8.95693539,23.1530908 8.95693539,23.1530908 8.95146479,23.1538215 C8.13032806,23.2634845 7.55356464,24.0180467 7.66322765,24.8391835 C7.77289065,25.6603202 8.52745292,26.2370836 9.34858965,26.1274206 L9.34858965,26.1274206 Z M17.0066591,25.0462427 C17.0121188,25.0454283 17.0121188,25.0454283 17.0175789,25.0446136 C17.8369369,24.9223683 18.4020584,24.1590479 18.279813,23.3396899 C18.1575677,22.5203319 17.3942473,21.9552104 16.5748893,22.0774558 C16.5694641,22.0782652 16.5694641,22.0782652 16.5640392,22.0790744 C15.7446783,22.2013005 15.1795389,22.9646076 15.301765,23.7839685 C15.4239911,24.6033294 16.1872982,25.1684688 17.0066591,25.0462427 L17.0066591,25.0462427 Z M24.8225082,24.4201748 C24.8297684,24.4189565 24.8297684,24.4189565 24.8370287,24.4177379 C25.922252,24.2355961 26.6543441,23.2081937 26.4722023,22.1229704 C26.2900605,21.0377471 25.2626581,20.3056549 24.1774348,20.4877968 C24.1702314,20.4890057 24.1702314,20.4890057 24.1630282,20.4902145 C23.0777996,20.6723249 22.3456777,21.6997061 22.5277881,22.7849347 C22.7098984,23.8701632 23.7372796,24.6022852 24.8225082,24.4201748 L24.8225082,24.4201748 Z M32.4725265,23.0495399 C33.5532108,22.8422598 34.2612448,21.7981584 34.0539647,20.7174741 C33.8466846,19.6367898 32.8025831,18.9287558 31.7218988,19.1360359 C31.714724,19.137412 31.714724,19.137412 31.7075489,19.138788 C30.6268567,19.3460265 29.9187826,20.3901008 30.1260211,21.470793 C30.3332597,22.5514853 31.3773339,23.2595594 32.4580262,23.0523208 C32.4652764,23.0509305 32.4652764,23.0509305 32.4725265,23.0495399 Z M39.8723866,20.8947688 C39.877909,20.8935242 39.877909,20.8935242 39.883431,20.8922795 C40.6915794,20.7101047 41.1990314,19.9072892 41.0168566,19.0991407 C40.8346818,18.2909923 40.0318663,17.7835404 39.2237179,17.9657152 C39.218279,17.9669412 39.218279,17.9669412 39.2128397,17.968167 C38.404681,18.1502959 37.8971834,18.9530826 38.0793123,19.7612414 C38.2614411,20.5694001 39.0642279,21.0768976 39.8723866,20.8947688 L39.8723866,20.8947688 Z M47.4276119,19.0082845 C47.4329844,19.0067855 47.4329844,19.0067855 47.4383562,19.0052864 C48.2362896,18.7825897 48.7026111,17.9552056 48.4799145,17.1572722 C48.2572179,16.3593388 47.4298337,15.8930173 46.6319003,16.1157139 C46.6266645,16.1171751 46.6266645,16.1171751 46.6214279,16.1186362 C45.8234736,16.3412577 45.3570742,17.168598 45.5796958,17.9665523 C45.8023173,18.7645067 46.6296576,19.230906 47.4276119,19.0082845 L47.4276119,19.0082845 Z M54.4138099,15.7087505 C54.4167849,15.7075945 54.4167849,15.7075945 54.419759,15.7064383 C54.8556933,15.5369585 55.0716973,15.0461733 54.9022174,14.610239 C54.7327376,14.1743047 54.2419524,13.9583007 53.8060181,14.1277806 C53.8032127,14.1288712 53.8032127,14.1288712 53.8004064,14.1299616 C53.3644359,14.2993484 53.148327,14.7900873 53.3177137,15.2260578 C53.4871005,15.6620283 53.9778394,15.8781372 54.4138099,15.7087505 L54.4138099,15.7087505 Z" id="Shape"></path>
+ </g>
+ <g id="top">
+ <path d="M1.4471104,12.2885536 C1.45019313,12.2881864 1.45019313,12.2881864 1.45327704,12.2878189 C1.91768952,12.2324787 2.24930811,11.8111359 2.1939679,11.3467234 C2.13862768,10.8823109 1.71728488,10.5506923 1.2528724,10.6060325 C1.24980572,10.606398 1.24980572,10.606398 1.24674021,10.6067632 C0.782326598,10.6620939 0.450699376,11.0834299 0.506030077,11.5478435 C0.561360778,12.0122571 0.982696791,12.3438844 1.4471104,12.2885536 L1.4471104,12.2885536 Z M9.34858965,12.1304907 C9.35409106,12.129756 9.35409106,12.129756 9.35959333,12.129021 C10.1807278,12.019341 10.7574756,11.2647668 10.6477955,10.4436323 C10.5381155,9.62249789 9.78354128,9.04575011 8.96240683,9.15543014 C8.95693539,9.15616095 8.95693539,9.15616095 8.95146479,9.15689157 C8.13032806,9.26655457 7.55356464,10.0211168 7.66322765,10.8422536 C7.77289065,11.6633903 8.52745292,12.2401537 9.34858965,12.1304907 L9.34858965,12.1304907 Z M17.0066591,11.0493128 C17.0121188,11.0484984 17.0121188,11.0484984 17.0175789,11.0476838 C17.8369369,10.9254384 18.4020584,10.1621181 18.279813,9.34276003 C18.1575677,8.52340201 17.3942473,7.95828052 16.5748893,8.08052587 C16.5694641,8.08133528 16.5694641,8.08133528 16.5640392,8.08214454 C15.7446783,8.20437064 15.1795389,8.96767771 15.301765,9.78703861 C15.4239911,10.6063995 16.1872982,11.1715389 17.0066591,11.0493128 L17.0066591,11.0493128 Z M24.8225082,10.4232459 C24.8297684,10.4220275 24.8297684,10.4220275 24.8370287,10.420809 C25.922252,10.2386672 26.6543441,9.21126476 26.4722023,8.12604147 C26.2900605,7.04081818 25.2626581,6.30872601 24.1774348,6.49086783 C24.1702314,6.4920768 24.1702314,6.4920768 24.1630282,6.49328559 C23.0777996,6.67539597 22.3456777,7.70277717 22.5277881,8.78800574 C22.7098984,9.87323431 23.7372796,10.6053563 24.8225082,10.4232459 L24.8225082,10.4232459 Z M32.4725265,9.05261002 C33.5532108,8.84532993 34.2612448,7.80122849 34.0539647,6.72054419 C33.8466846,5.63985989 32.8025831,4.93182589 31.7218988,5.13910599 C31.714724,5.14048211 31.714724,5.14048211 31.7075489,5.14185807 C30.6268567,5.34909665 29.9187826,6.39317088 30.1260211,7.47386314 C30.3332597,8.5545554 31.3773339,9.26262952 32.4580262,9.05539095 C32.4652764,9.05400057 32.4652764,9.05400057 32.4725265,9.05261002 Z M39.8723866,6.89476879 C39.877909,6.8935242 39.877909,6.8935242 39.883431,6.89227947 C40.6915794,6.71010471 41.1990314,5.90728916 41.0168566,5.09914075 C40.8346818,4.29099233 40.0318663,3.78354042 39.2237179,3.96571517 C39.218279,3.96694116 39.218279,3.96694116 39.2128397,3.96816703 C38.404681,4.15029588 37.8971834,4.9530826 38.0793123,5.76124136 C38.2614411,6.56940012 39.0642279,7.07689764 39.8723866,6.89476879 L39.8723866,6.89476879 Z M47.4276119,5.00828445 C47.4329844,5.00678549 47.4329844,5.00678549 47.4383562,5.00528637 C48.2362896,4.78258973 48.7026111,3.95520561 48.4799145,3.15727221 C48.2572179,2.35933881 47.4298337,1.89301728 46.6319003,2.11571391 C46.6266645,2.1171751 46.6266645,2.1171751 46.6214279,2.11863616 C45.8234736,2.34125773 45.3570742,3.16859798 45.5796958,3.96655233 C45.8023173,4.76450667 46.6296576,5.23090603 47.4276119,5.00828445 L47.4276119,5.00828445 Z M54.419759,2.30643871 C54.8556933,2.13695884 55.0716973,1.6461737 54.9022174,1.21023941 C54.7327376,0.774305114 54.2419524,0.558301127 53.8060181,0.727780997 C53.8032127,0.728871549 53.8032127,0.728871549 53.8004064,0.729962021 C53.3644359,0.89934874 53.148327,1.39008772 53.3177137,1.82605822 C53.4871005,2.26202871 53.9778394,2.47813756 54.4138099,2.30875084 C54.4167849,2.30759485 54.4167849,2.30759485 54.419759,2.30643871 Z" id="Shape"></path>
+ <path d="M1.67760355,20.096503 C1.68306395,20.0958524 1.68306395,20.0958524 1.68852642,20.0952015 C2.51113381,19.9971782 3.09852524,19.2508595 3.00050189,18.4282521 C2.90247854,17.6056447 2.15615986,17.0182533 1.33355246,17.1162767 C1.3281205,17.1169239 1.3281205,17.1169239 1.3226906,17.1175709 C0.500081196,17.2155774 -0.0873255124,17.961884 0.0106809923,18.7844934 C0.108687497,19.6071028 0.854994145,20.1945095 1.67760355,20.096503 L1.67760355,20.096503 Z M9.34858965,19.1274206 C9.35409106,19.1266859 9.35409106,19.1266859 9.35959333,19.1259509 C10.1807278,19.0162709 10.7574756,18.2616967 10.6477955,17.4405622 C10.5381155,16.6194278 9.78354128,16.04268 8.96240683,16.15236 C8.95693539,16.1530908 8.95693539,16.1530908 8.95146479,16.1538215 C8.13032806,16.2634845 7.55356464,17.0180467 7.66322765,17.8391835 C7.77289065,18.6603202 8.52745292,19.2370836 9.34858965,19.1274206 L9.34858965,19.1274206 Z M17.1767435,18.6256231 C17.1839958,18.6245412 17.1839958,18.6245412 17.1912486,18.6234592 C18.27963,18.4610765 19.0303002,17.4471319 18.8679175,16.3587506 C18.7055348,15.2703693 17.6915903,14.519699 16.6032089,14.6820817 C16.5960024,14.6831569 16.5960024,14.6831569 16.5887964,14.6842319 C15.5004112,14.846589 14.7497172,15.8605159 14.9120743,16.948901 C15.0744314,18.0372862 16.0883584,18.7879802 17.1767435,18.6256231 L17.1767435,18.6256231 Z M24.8370287,17.4177379 C25.922252,17.2355961 26.6543441,16.2081937 26.4722023,15.1229704 C26.2900605,14.0377471 25.2626581,13.3056549 24.1774348,13.4877968 C24.1702314,13.4890057 24.1702314,13.4890057 24.1630282,13.4902145 C23.0777996,13.6723249 22.3456777,14.6997061 22.5277881,15.7849347 C22.7098984,16.8701632 23.7372796,17.6022852 24.8225082,17.4201748 C24.8297684,17.4189565 24.8297684,17.4189565 24.8370287,17.4177379 Z M32.4725265,16.061085 C33.5532108,15.853199 34.2612448,14.8060455 34.0539647,13.7222022 C33.8466846,12.6383589 32.8025831,11.9282552 31.7218988,12.1361412 C31.714724,12.1375214 31.714724,12.1375214 31.7075489,12.1389013 C30.6268567,12.3467457 29.9187826,13.3938719 30.1260211,14.4777232 C30.3332597,15.5615745 31.3773339,16.2717185 32.4580262,16.0638741 C32.4652764,16.0624797 32.4652764,16.0624797 32.4725265,16.061085 Z M40.0707225,14.4695476 C40.0780573,14.4678946 40.0780573,14.4678946 40.0853916,14.4662413 C41.158768,14.2242783 41.8327617,13.1579849 41.5907986,12.0846085 C41.3488355,11.011232 40.2825422,10.3372384 39.2091657,10.5792015 C39.2019419,10.5808298 39.2019419,10.5808298 39.1947175,10.582458 C38.1213273,10.8243601 37.447273,11.8906152 37.6891752,12.9640053 C37.9310773,14.0373955 38.9973324,14.7114498 40.0707225,14.4695476 L40.0707225,14.4695476 Z M47.4276119,12.0082845 C47.4329844,12.0067855 47.4329844,12.0067855 47.4383562,12.0052864 C48.2362896,11.7825897 48.7026111,10.9552056 48.4799145,10.1572722 C48.2572179,9.35933881 47.4298337,8.89301728 46.6319003,9.11571391 C46.6266645,9.1171751 46.6266645,9.1171751 46.6214279,9.11863616 C45.8234736,9.34125773 45.3570742,10.168598 45.5796958,10.9665523 C45.8023173,11.7645067 46.6296576,12.230906 47.4276119,12.0082845 L47.4276119,12.0082845 Z M54.8999721,9.57562965 C54.9052414,9.57358217 54.9052414,9.57358217 54.9105092,9.57153441 C55.6826371,9.27135123 56.0652239,8.40207131 55.7650408,7.62994336 C55.4648576,6.85781542 54.5955777,6.4752286 53.8234497,6.77541179 C53.8184808,6.77734338 53.8184808,6.77734338 53.8135101,6.77927482 C53.0413181,7.07929302 52.6585455,7.94849117 52.9585637,8.72068323 C53.2585819,9.4928753 54.12778,9.87564785 54.8999721,9.57562965 L54.8999721,9.57562965 Z" id="Shape"></path>
+ <path d="M1.45327704,26.6978168 C1.54647464,26.6867112 1.63432439,26.660866 1.7147722,26.6228911 C2.03520341,26.4716332 2.23820252,26.1279362 2.1939679,25.7567213 C2.13862768,25.2923089 1.71728488,24.9606903 1.2528724,25.0160305 C1.24980572,25.0163959 1.24980572,25.0163959 1.24674021,25.0167611 C0.782326598,25.0720918 0.450699376,25.4934278 0.506030077,25.9578415 C0.561360778,26.4222551 0.982696791,26.7538823 1.4471104,26.6985516 C1.45019313,26.6981843 1.45019313,26.6981843 1.45327704,26.6978168 Z M9.34858965,26.1274206 C9.35409106,26.1266859 9.35409106,26.1266859 9.35959333,26.1259509 C10.1807278,26.0162709 10.7574756,25.2616967 10.6477955,24.4405622 C10.5381155,23.6194278 9.78354128,23.04268 8.96240683,23.15236 C8.95693539,23.1530908 8.95693539,23.1530908 8.95146479,23.1538215 C8.13032806,23.2634845 7.55356464,24.0180467 7.66322765,24.8391835 C7.77289065,25.6603202 8.52745292,26.2370836 9.34858965,26.1274206 L9.34858965,26.1274206 Z M17.0066591,25.0462427 C17.0121188,25.0454283 17.0121188,25.0454283 17.0175789,25.0446136 C17.8369369,24.9223683 18.4020584,24.1590479 18.279813,23.3396899 C18.1575677,22.5203319 17.3942473,21.9552104 16.5748893,22.0774558 C16.5694641,22.0782652 16.5694641,22.0782652 16.5640392,22.0790744 C15.7446783,22.2013005 15.1795389,22.9646076 15.301765,23.7839685 C15.4239911,24.6033294 16.1872982,25.1684688 17.0066591,25.0462427 L17.0066591,25.0462427 Z M24.8225082,24.4201748 C24.8297684,24.4189565 24.8297684,24.4189565 24.8370287,24.4177379 C25.922252,24.2355961 26.6543441,23.2081937 26.4722023,22.1229704 C26.2900605,21.0377471 25.2626581,20.3056549 24.1774348,20.4877968 C24.1702314,20.4890057 24.1702314,20.4890057 24.1630282,20.4902145 C23.0777996,20.6723249 22.3456777,21.6997061 22.5277881,22.7849347 C22.7098984,23.8701632 23.7372796,24.6022852 24.8225082,24.4201748 L24.8225082,24.4201748 Z M32.4725265,23.0495399 C33.5532108,22.8422598 34.2612448,21.7981584 34.0539647,20.7174741 C33.8466846,19.6367898 32.8025831,18.9287558 31.7218988,19.1360359 C31.714724,19.137412 31.714724,19.137412 31.7075489,19.138788 C30.6268567,19.3460265 29.9187826,20.3901008 30.1260211,21.470793 C30.3332597,22.5514853 31.3773339,23.2595594 32.4580262,23.0523208 C32.4652764,23.0509305 32.4652764,23.0509305 32.4725265,23.0495399 Z M39.8723866,20.8947688 C39.877909,20.8935242 39.877909,20.8935242 39.883431,20.8922795 C40.6915794,20.7101047 41.1990314,19.9072892 41.0168566,19.0991407 C40.8346818,18.2909923 40.0318663,17.7835404 39.2237179,17.9657152 C39.218279,17.9669412 39.218279,17.9669412 39.2128397,17.968167 C38.404681,18.1502959 37.8971834,18.9530826 38.0793123,19.7612414 C38.2614411,20.5694001 39.0642279,21.0768976 39.8723866,20.8947688 L39.8723866,20.8947688 Z M47.4276119,19.0082845 C47.4329844,19.0067855 47.4329844,19.0067855 47.4383562,19.0052864 C48.2362896,18.7825897 48.7026111,17.9552056 48.4799145,17.1572722 C48.2572179,16.3593388 47.4298337,15.8930173 46.6319003,16.1157139 C46.6266645,16.1171751 46.6266645,16.1171751 46.6214279,16.1186362 C45.8234736,16.3412577 45.3570742,17.168598 45.5796958,17.9665523 C45.8023173,18.7645067 46.6296576,19.230906 47.4276119,19.0082845 L47.4276119,19.0082845 Z M54.4138099,15.7087505 C54.4167849,15.7075945 54.4167849,15.7075945 54.419759,15.7064383 C54.8556933,15.5369585 55.0716973,15.0461733 54.9022174,14.610239 C54.7327376,14.1743047 54.2419524,13.9583007 53.8060181,14.1277806 C53.8032127,14.1288712 53.8032127,14.1288712 53.8004064,14.1299616 C53.3644359,14.2993484 53.148327,14.7900873 53.3177137,15.2260578 C53.4871005,15.6620283 53.9778394,15.8781372 54.4138099,15.7087505 L54.4138099,15.7087505 Z" id="Shape"></path>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc-tool/resources/_includes/toc.html b/doc-tool/resources/_includes/toc.html
new file mode 100644
index 000000000..15952ef78
--- /dev/null
+++ b/doc-tool/resources/_includes/toc.html
@@ -0,0 +1,11 @@
+<ul class="toc">
+ <li class="logo-li">
+ <a id="home-button" href="{{ site.baseurl }}/index.html">
+ {% include "scala-logo.svg" %}
+ </a>
+ </li>
+ {% assign parent = page.path | first %}
+ {% for title in sidebar %}
+ <li>{% renderTitle title, parent %}</li>
+ {% endfor %}
+</ul>
diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html
new file mode 100644
index 000000000..26a4290da
--- /dev/null
+++ b/doc-tool/resources/_layouts/api-page.html
@@ -0,0 +1,171 @@
+---
+layout: sidebar
+extraCSS:
+ - css/api-page.css
+---
+
+<script>
+ document.title = "{{ site.project }} API - {{ entity.name }}"
+</script>
+
+<div id="entity-container">
+ <div id="entity-title">
+ <span id="entity-annotations">
+ {% for annot in entity.annotations %}@{{ annot | split: '.' | last }} {% endfor %}
+ </span>
+ <span id="entity-modifiers">
+ {{ entity.modifiers | join: " " }}
+ </span>
+ <span id="entity-kind">
+ {{ entity.kind }}
+ </span>
+ <span id="entity-name">
+ {{ entity.name }}
+ </span>
+ {% if entity.typeParams.size > 0 %}
+ <span id="entity-type-params">
+ <span class="no-left">[</span>
+ {% for param in entity.typeParams %}
+ <span class="no-left">
+ {% if forloop.last %}
+ {{ param }}
+ {% else %}
+ {{ param }},
+ {% endif %}
+ </span>
+ {% endfor %}
+ <span class="no-left">]</span>
+ </span>
+ {% endif %}
+ {% if entity.superTypes.size > 0 %}
+ <div id="super-types">
+ {% for super in entity.superTypes %}
+ {% if forloop.first %}
+ <span class="keyword">extends</span>
+ {% else %}
+ <span class="keyword">with</span>
+ {% endif %}
+ <span class="entity-super-type">{% renderLink super %}</span>
+ {% endfor %}
+ </div>
+ {% endif %}
+ </div>
+
+ {% if entity.comment.body %}
+ <div id="entity-body" class="entity-section">
+ {{ entity.comment.body }}
+ </div>
+ {% endif %}
+
+ <h1 class="section {% if entity.constructors == null or entity.constructors.size == 0 %}empty{% endif %}">
+ Constructors
+ </h1>
+
+ <div id="entity-constructors" class="entity-section {% if entity.constructors == null or entity.constructors.size == 0 %}empty{% endif %}">
+ {% for constructor in entity.constructors %}
+ {% for plist in constructor %}
+ <div class="member">
+ <div class="member-title">
+ <span class="member-name">{{ entity.name }}</span>
+ <span class="no-left">(</span>
+ {% if plist.isImplicit %}
+ <span class="no-left keyword">implicit</span>
+ {% endif %}
+ {% for namedRef in plist.list %}
+ <span class="{% if forloop.first %}no-left{% endif %}">
+ {{ namedRef.title }}:{% if namedRef.isByName %} =&gt;{% endif %}
+ </span>
+ {% renderRef namedRef.ref %}
+ {% if forloop.last != true %}
+ <span class="no-left">, </span>
+ {% endif %}
+ {% endfor %}
+ <span class="no-left">)</span>
+ </div>
+ </div>
+ {% endfor %}
+ {% endfor %}
+ </div>
+
+ <h1 class="section {% if entity.hasVisibleMembers == false %}empty{% endif %}">
+ Members
+ </h1>
+
+ <div id="entity-members" class="entity-section {% if entity.hasVisibleMembers == false %}empty{% endif %}">
+ {% for member in entity.members %}
+ <div id="{{ member.signature }}" class="member {% if member.isPrivate %}private{% elsif member.isProtected %}protected{% endif %}">
+ <div class="member-title">
+ <span class="expand-button" onclick="toggleMemberBody(this, '{{ member.signature }}');">[+]</span>
+ <span class="member-annotations">
+ {% for annot in member.annotations %}@{{ annot | split: '.' | last }} {% endfor %}
+ </span>
+ <span class="member-modifiers">
+ {{ member.modifiers | join: " " }}
+ </span>
+ <span class="member-kind">
+ {{ member.kind }}
+ </span>
+ <span class="member-name {% if member.isImplicitlyAddedFrom != null %}implicitly-added{% endif %}">
+ {% if member.kind == "class" or member.kind == "case class" or member.kind == "object" or member.kind == "trait" %}
+ <a href="{{ site.baseurl }}/api/{{ member.path | join: "/" }}.html">{{ member.name }}</a>
+ {% elsif member.kind == "package" %}
+ <a href="{{ site.baseurl }}/api/{{ member.path | join: "/" }}/index.html">{{ member.name }}</a>
+ {% else %}
+ {{ member.name }}
+ {% endif %}
+ </span>
+
+ {% if member.kind == "def" and member.paramLists.size > 0 %}
+ {% for plist in member.paramLists %}
+ <span class="no-left">(</span>
+ {% if plist.isImplicit %}
+ <span class="no-left keyword">implicit</span>
+ {% endif %}
+ {% for namedRef in plist.list %}
+ <span class="{% if forloop.first %}no-left{% endif %}">
+ {{ namedRef.title }}:{% if namedRef.isByName %} =&gt;{% endif %}
+ </span>
+ {% renderRef namedRef.ref %}
+ {% if forloop.last != true %}
+ <span class="no-left">, </span>
+ {% endif %}
+ {% endfor %}
+ <span class="no-left">)</span>
+ {% endfor %}
+ {% endif %}
+
+ {% if member.kind == "type" and member.alias != null %}
+ <span class="type-alias">
+ <span class="equals"> = </span>
+ {% renderRef member.alias %}
+ </span>
+ {% endif %}
+
+ {% if member.returnValue %}
+ <span class="no-left">: {% renderRef member.returnValue %}</span>
+ {% endif %}
+ </div><!-- end member-title -->
+
+ <div class="member-body">
+ <div class="member-body-short" id="short-body-{{ member.signature }}">
+ {{ member.comment.short }}
+ </div>
+ <div class="member-body-long" id ="long-body-{{ member.signature }}">
+ {{ member.comment.body }}
+ </div>
+ </div>
+ <script>
+ function toggleMemberBody(span, sig) {
+ var shortBody = document.getElementById("short-body-" + sig);
+ var longBody = document.getElementById("long-body-" + sig);
+
+ shortBody.classList.toggle("toggled")
+ longBody.classList.toggle("toggled")
+
+ span.innerHTML = (span.innerHTML == "[+]") ? "[-]" : "[+]";
+ }
+ </script>
+ </div><!-- end member -->
+ {% endfor %}
+ </div>
+</div><!-- end entity-container -->
diff --git a/doc-tool/resources/_layouts/blog-page.html b/doc-tool/resources/_layouts/blog-page.html
new file mode 100644
index 000000000..b99a16b9c
--- /dev/null
+++ b/doc-tool/resources/_layouts/blog-page.html
@@ -0,0 +1,28 @@
+---
+layout: sidebar
+---
+
+<div id="post-title">
+ <h3 id="post-date">
+ {{ page.date | date: '%B %d, %Y' }}
+ </h3>
+ <h1 id="main-title">{{ page.title }}</h1>
+ {% if page.subTitle %}
+ <h2 id="sub-title">{{ page.subTitle }}</h2>
+ {% endif %}
+</div>
+
+<div id="blog-post-container">
+ {{ content }}
+</div>
+
+{% if page.author %}
+<div id="post-footer">
+ {% if page.authorImg %}
+ <img id="author-image" src="{{ site.baseurl }}/{{ page.authorImg }}">
+ {% endif %}
+ <span id="post-author">
+ {% if page.authorImg == null %}- {% endif %}{{ page.author }}
+ </span>
+</div>
+{% endif %}
diff --git a/doc-tool/resources/_layouts/doc-page.html b/doc-tool/resources/_layouts/doc-page.html
new file mode 100644
index 000000000..14220aef7
--- /dev/null
+++ b/doc-tool/resources/_layouts/doc-page.html
@@ -0,0 +1,8 @@
+---
+layout: sidebar
+---
+
+<h1 id="doc-page-title">{{ page.title }}</h1>
+<div id="doc-page-container">
+ {{ content }}
+</div>
diff --git a/doc-tool/resources/_layouts/index.html b/doc-tool/resources/_layouts/index.html
new file mode 100644
index 000000000..5be2d9794
--- /dev/null
+++ b/doc-tool/resources/_layouts/index.html
@@ -0,0 +1,4 @@
+---
+layout: main
+---
+<h1>{{ content }}</h1>
diff --git a/doc-tool/resources/_layouts/main.html b/doc-tool/resources/_layouts/main.html
new file mode 100644
index 000000000..7c63ec610
--- /dev/null
+++ b/doc-tool/resources/_layouts/main.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+
+ <title>{{ page.title }}</title>
+
+ <link
+ rel="stylesheet"
+ href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"
+ integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi"
+ crossorigin="anonymous"
+ >
+ <link
+ rel="stylesheet"
+ href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"
+ >
+
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+
+ <link
+ rel="stylesheet"
+ href="{{ site.baseurl }}/css/dottydoc.css"
+ >
+
+ <link
+ rel="stylesheet"
+ href="{{ site.baseurl }}/css/color-brewer.css"
+ >
+
+ {% for css in page.extraCSS %}
+ <link
+ rel="stylesheet"
+ href="{{ site.baseurl }}/{{ css }}"
+ >
+ {% endfor %}
+ </head>
+ <body>
+
+ {{ content }}
+
+ <script
+ src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"
+ integrity="sha384-3ceskX3iaEnIogmQchP8opvBy3Mi7Ce34nWjpBIwVTHfGYWQS9jwHDVRnpKKHJg7"
+ crossorigin="anonymous"
+ ></script>
+ <script
+ src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.3.7/js/tether.min.js"
+ integrity="sha384-XTs3FgkjiBgo8qjEjBk0tGmf3wPrWtA6coPfQDfFEY8AnYJwjalXCiosYRBIBZX8"
+ crossorigin="anonymous"
+ ></script>
+ <script
+ src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"
+ integrity="sha384-BLiI7JTZm+JWlgKa0M0kGRpJbF2J8q+qreVrKBC47e3K6BW78kGLrCkeRX6I9RoK"
+ crossorigin="anonymous"
+ ></script>
+ <script src="{{ site.baseurl }}/js/highlight.pack.js"></script>
+ {% for js in page.extraJS %}
+ <script src="{{ site.baseurl }}/{{ js }}"></script>
+ {% endfor %}
+ <script>
+ $(document).ready(function() {
+ $('pre code').each(function(i, block) {
+ hljs.highlightBlock(block);
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/doc-tool/resources/_layouts/sidebar.html b/doc-tool/resources/_layouts/sidebar.html
new file mode 100644
index 000000000..b3947c884
--- /dev/null
+++ b/doc-tool/resources/_layouts/sidebar.html
@@ -0,0 +1,49 @@
+---
+layout: main
+---
+
+<div id="content-wrapper">
+ <div class="index-wrapper">
+ {% include "toc" %}
+ <ul class="index-entities">
+ {% if docs.size > 0 %}
+ <li class="index-title">
+ <span>API</span>
+ </li>
+ {% endif %}
+ {% for pkg in docs %}
+ <li class="index-entity entity-package">
+ <a class="entity-name" href="{{ site.baseurl }}/api/{{ pkg.path | join: "/" }}/index.html">{{ pkg.name }}</a>
+ </li>
+ {% for member in pkg.children %}
+ {% if member.kind == "object" and member.hasCompanion %}
+ {% elsif member.kind != "package" %}
+ <li class="index-entity {% if member.hasCompanion %} with-companion {% endif %}">
+ <div class="entity-kinds">
+ {% if member.hasCompanion %}
+ <a class="letter-anchor object" href="{{ site.baseurl }}/api/{{ member.companionPath | join: "/" }}.html">O</a>
+ {% endif %}
+ <a class="letter-anchor {{ member.kind }}" href="{{ site.baseurl }}/api/{{ member.path | join: "/" }}.html">{{ member.kind | first | capitalize }}</a>
+ </div>
+ <a class="entity-name" href="{{ site.baseurl }}/api/{{ member.path | join: "/" }}.html">{{ member.name }}</a>
+ </li>
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ </ul>
+ </div>
+ <div id="content-body">
+ <div id="menu-toggle" onclick="toggleMenu()">
+ <i class="fa fa-bars" aria-hidden="true"></i>
+ </div>
+ {{ content }}
+ </div>
+</div>
+
+
+<script>
+function toggleMenu() {
+ var wrapper = document.getElementById("content-wrapper");
+ wrapper.classList.toggle("toggled");
+}
+</script>
diff --git a/doc-tool/resources/css/api-page.css b/doc-tool/resources/css/api-page.css
new file mode 100644
index 000000000..380efb834
--- /dev/null
+++ b/doc-tool/resources/css/api-page.css
@@ -0,0 +1,139 @@
+/** Fonts */
+@import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700,600);
+
+div#entity-container {
+ margin-top: 10px;
+ padding: 0 20px 20px;
+}
+
+div#entity-title {
+ color: #34495e;
+ font-family: "Helvetica","Arial",sans-serif;
+ font-weight: 400;
+ margin-bottom: 30px;
+ font-size: 2.5rem;
+}
+
+div#entity-title > span#entity-annotations,
+div#entity-title > span#entity-modifiers,
+div#entity-title > span#entity-kind {
+ font-weight: 100;
+}
+
+div#entity-title > div#super-types > span.keyword {
+ font-weight: 100;
+}
+
+div#entity-title > div#super-types > span.keyword,
+div#entity-title > div#super-types > span.entity-super-type {
+ font-size: 25px;
+}
+
+div#entity-title > div#super-types> span.entity-super-type > a,
+div#entity-title > div#super-types> span.entity-super-type > a:focus {
+ text-decoration: none;
+ color: #34495e;
+}
+
+div#entity-title > div#super-types> span.entity-super-type > a:hover {
+ text-decoration: underline;
+}
+
+div#entity-title span.no-left {
+ margin-left: -9px;
+}
+
+div#entity-title span.no-right {
+ margin-right: -9px;
+}
+
+div#entity-body table > tbody > tr > td {
+ padding: 10px;
+}
+
+div.entity-section {
+ background-color: #fff;
+ border-radius: 4px;
+ margin: 0;
+ padding: 30px;
+}
+
+div.entity-section *:last-child {
+ margin-bottom: 0px;
+}
+
+h1.section {
+ margin: 30px 0;
+}
+
+.empty {
+ display: none;
+}
+
+div.entity-section > div.member.protected {
+ display: none;
+}
+
+div.entity-section > div.member.private {
+ display: none;
+}
+
+div.entity-section > div.member {
+ margin-bottom: 30px;
+}
+
+div.entity-section > div.member:last-child {
+ margin-bottom: 0px;
+}
+
+div.entity-section > div.member > div.member-title {
+ font-family: "Source Code Pro", sans-serif;
+}
+
+div.entity-section > div.member > div.member-title > span.member-name {
+ color: #458;
+ font-weight: 600;
+}
+
+div.entity-section > div.member > div.member-title > span.member-name.implicitly-added {
+ color: #019875;
+}
+
+div.entity-section > div.member > div.member-title span.keyword {
+ font-weight: 600;
+ margin-right: 11px;
+}
+
+div.entity-section > div.member > div.member-title span.no-left {
+ margin-left: -11px;
+}
+
+div.entity-section > div.member > div.member-title span.no-right {
+ margin-right: -11px;
+}
+
+div.entity-section > div.member > div.member-title > span.expand-button {
+ color: rgba(167, 161, 161, 0.5);
+}
+
+div.entity-section > div.member > div.member-title > span.expand-button:hover {
+ color: rgb(167, 161, 161);
+ cursor: pointer;
+ user-select: none;
+}
+
+div.entity-section > div.member > div.member-body {
+ margin: 5px 0 0 39px;
+}
+
+div.entity-section > div.member > div.member-body > div.member-body-short.toggled {
+ display: none;
+}
+
+div.entity-section > div.member > div.member-body > div.member-body-long {
+ display: none;
+}
+
+div.entity-section > div.member > div.member-body > div.member-body-long.toggled {
+ display: block;
+}
diff --git a/doc-tool/resources/css/color-brewer.css b/doc-tool/resources/css/color-brewer.css
new file mode 100644
index 000000000..7934d986a
--- /dev/null
+++ b/doc-tool/resources/css/color-brewer.css
@@ -0,0 +1,71 @@
+/*
+
+Colorbrewer theme
+Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock <mike@ocks.org>
+Ported by Fabrício Tavares de Oliveira
+
+*/
+
+.hljs {
+ display: block;
+ overflow-x: auto;
+ padding: 0.5em;
+ background: #fff;
+}
+
+.hljs,
+.hljs-subst {
+ color: #000;
+}
+
+.hljs-string,
+.hljs-meta,
+.hljs-symbol,
+.hljs-template-tag,
+.hljs-template-variable,
+.hljs-addition {
+ color: #756bb1;
+}
+
+.hljs-comment,
+.hljs-quote {
+ color: #636363;
+}
+
+.hljs-number,
+.hljs-regexp,
+.hljs-literal,
+.hljs-bullet,
+.hljs-link {
+ color: #31a354;
+}
+
+.hljs-deletion,
+.hljs-variable {
+ color: #88f;
+}
+
+
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-title,
+.hljs-section,
+.hljs-built_in,
+.hljs-doctag,
+.hljs-type,
+.hljs-tag,
+.hljs-name,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-strong {
+ color: #3182bd;
+}
+
+.hljs-emphasis {
+ font-style: italic;
+}
+
+.hljs-attribute {
+ color: #e6550d;
+}
diff --git a/doc-tool/resources/css/dottydoc.css b/doc-tool/resources/css/dottydoc.css
new file mode 100644
index 000000000..7e7c501bf
--- /dev/null
+++ b/doc-tool/resources/css/dottydoc.css
@@ -0,0 +1,330 @@
+html {
+ height: 100%;
+}
+body {
+ min-height: 100%;
+}
+
+div#content-wrapper {
+ min-height: 100vh;
+ padding-left: 250px;
+ transition: all 0.5s ease;
+}
+
+div#content-wrapper.toggled {
+ padding-left: 0;
+}
+
+div.index-wrapper {
+ background-color: #fafafa;
+ width: 250px;
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+div#doc-page-container > h1 {
+ border-bottom: 1px solid #eee;
+ padding-bottom: 0.3em;
+}
+
+div#doc-page-container > h1 {
+ margin: 3rem 0 0.5rem 0;
+}
+
+div#doc-page-container > h3 {
+ font-size: 1.5rem;
+}
+
+div#doc-page-container > h4 {
+ font-size: 1.25rem;
+}
+
+div#doc-page-container > h5 {
+ font-size: 1rem;
+}
+
+div#entity-container h1 > a,
+div#entity-container h2 > a,
+div#entity-container h3 > a,
+div#entity-container h4 > a,
+div#entity-container h5 > a,
+div#entity-container h6 > a,
+div#doc-page-container > h1 > a,
+div#doc-page-container > h2 > a,
+div#doc-page-container > h3 > a,
+div#doc-page-container > h4 > a,
+div#doc-page-container > h5 > a,
+div#doc-page-container > h6 > a {
+ text-decoration: none;
+ color: #373a3c;
+}
+
+div#entity-container h1 > a:hover,
+div#entity-container h2 > a:hover,
+div#entity-container h3 > a:hover,
+div#entity-container h4 > a:hover,
+div#entity-container h5 > a:hover,
+div#entity-container h6 > a:hover,
+div#doc-page-container > h1 > a:hover,
+div#doc-page-container > h2 > a:hover,
+div#doc-page-container > h3 > a:hover,
+div#doc-page-container > h4 > a:hover,
+div#doc-page-container > h5 > a:hover,
+div#doc-page-container > h6 > a:hover {
+ text-decoration: underline;
+}
+
+div#entity-container h1 > a:focus,
+div#entity-container h2 > a:focus,
+div#entity-container h3 > a:focus,
+div#entity-container h4 > a:focus,
+div#entity-container h5 > a:focus,
+div#entity-container h6 > a:focus,
+div#doc-page-container > h1 > a:focus,
+div#doc-page-container > h2 > a:focus,
+div#doc-page-container > h3 > a:focus,
+div#doc-page-container > h4 > a:focus,
+div#doc-page-container > h5 > a:focus,
+div#doc-page-container > h6 > a:focus {
+ outline: none;
+}
+
+div#content-body {
+ border-left: 1px solid #e0e0e0;
+ box-shadow: -3px 0px 5px -2px rgba(0,0,0,0.14);
+ position: relative;
+ padding: 10px;
+ background-color: #f4f3f4;
+ min-height: 100vh;
+}
+
+div#menu-toggle {
+ color: #837F84;
+ outline: none;
+ padding-left: 20px;
+ padding-top: 10px;
+}
+
+div#menu-toggle:hover {
+ color: rgba(0, 0, 0, 0.4);
+ cursor: pointer;
+}
+
+ul.index-entities {
+ list-style-type: none;
+ padding-left: 0;
+}
+
+ul.toc {
+ list-style-type: none;
+ padding-top: 18px;
+ padding-left: 0;
+}
+
+ul.toc > li:hover {
+ background-color: transparent;
+}
+
+ul.toc > li.toc-title {
+ margin-top: 1rem;
+}
+
+ul.toc > li.toc-title > a {
+ font-size: 16px;
+ font-weight: bold;
+}
+
+ul.toc > li > a#home-button,
+ul.toc > li > a#home-button:hover {
+ text-align: center;
+ background: transparent;
+}
+
+ul.toc > li > a#home-button svg g#logo-foreground {
+ fill: rgba(202, 68, 94, 1);
+}
+
+ul.toc > li > a#home-button svg g#logo-background {
+ fill: rgba(202, 68, 94, 0.45);
+}
+
+ul.toc > li > a {
+ width: 100%;
+ user-select: none;
+}
+
+ul.toc > li,
+ul.index-entities > li {
+ line-height: 40px;
+ display: inline-block;
+ width: 100%;
+}
+
+ul.index-entities > li.index-entity:not(.entity-package) {
+ width: calc(100% + 40px);
+ transition: all 0.2s ease;
+ margin-left: -40px;
+}
+
+ul.index-entities > li.index-entity.with-companion {
+ width: calc(100% + 80px);
+ margin-left: -80px;
+}
+
+ul.index-entities > li.index-entity:hover {
+ margin-left: 0;
+}
+
+ul.toc > li.logo-li > a {
+ margin: 0;
+ padding: 0;
+ float: none;
+}
+
+li.index-entity.entity-package > a.entity-name {
+ color: #ff4081;
+ text-decoration: none;
+}
+
+ul.toc > li > a,
+ul.index-entities > li > a.entity-name {
+ font-size: 13px;
+ display: block;
+ padding: 0 0 0 24px;
+ color: rgba(0,0,0,.87);
+ background: transparent;
+ cursor: pointer;
+ float: left;
+}
+
+ul.index-entities > li > div.entity-kinds {
+ float: left;
+}
+
+ul.index-entities > li > div.entity-kinds > a.letter-anchor {
+ float: left;
+ width: 40px;
+ height: 40px;
+ color: white;
+ display: block;
+ text-align: center;
+ text-decoration: none;
+}
+
+ul.index-entities > li > div.entity-kinds > a.letter-anchor:focus,
+ul.index-entities > li > div.entity-kinds > a.letter-anchor:hover {
+ text-decoration: none;
+}
+
+ul.index-entities > li > div.entity-kinds > a.letter-anchor.object {
+ background-color: rgb(44, 108, 141);
+}
+
+ul.index-entities > li > div.entity-kinds > a.letter-anchor.class {
+ background-color: rgb(68, 173, 125);
+}
+
+ul.index-entities > li > div.entity-kinds > a.letter-anchor.trait {
+ background-color: rgb(25, 170, 207);
+}
+
+ul.toc > li > ul.show {
+ display: block;
+ list-style-type: none;
+ font-size: 13px;
+}
+
+ul.toc > li > ul.hide {
+ display: none;
+}
+
+ul.index-entities > li.index-title > span {
+ font-size: 16px;
+ font-weight: bold;
+ color: rgba(0,0,0,.87);
+ padding: 0 24px;
+}
+
+ul.index-entities > li.index-title:hover {
+ background-color: transparent;
+}
+
+li.index-entity > a:focus {
+ text-decoration: none;
+}
+
+ul.index-entities > li:hover,
+ul.toc > li > a:hover {
+ background-color: rgba(0, 0, 0, 0.2);
+}
+
+ul.index-entities > li > a:hover,
+ul.toc > li > a:hover {
+ text-decoration: none;
+}
+
+.darken {
+ background-color: rgba(0, 0, 0, 0.2);
+}
+
+div#post-title,
+div#post-footer,
+h1#doc-page-title {
+ margin-left: 20px;
+ margin-top: 10px;
+}
+
+div#post-title > h2#sub-title {
+ font-weight: 100;
+ font-size: 24px;
+}
+
+div#post-title > h3#post-date {
+ font-weight: 100;
+ font-size: 20px;
+ margin-bottom: 2px;
+}
+
+div#blog-post-container,
+div#doc-page-container {
+ background-color: #fff;
+ padding: 10px;
+ border-radius: 4px;
+ margin: 20px;
+ padding: 30px;
+}
+
+div#doc-page-container > p + h1 {
+ margin-bottom: 20px;
+}
+
+div#post-footer > img#author-image {
+ width: 100px;
+ height: auto;
+ border-radius: 50%;
+}
+
+div#post-footer > span#post-author {
+ margin-left: 10px;
+ font-weight: 100;
+}
+
+pre {
+ padding: 0;
+ font-size: 13px;
+ background: rgba(244, 243, 244, 0.6);
+ border-radius: 2px;
+ margin-top: 20px;
+ border: 1px solid rgba(0,0,0,0.1);
+}
+
+pre > code.language-none,
+pre > code.hljs {
+ display: block;
+ padding: 10px;
+ background: transparent;
+}
diff --git a/doc-tool/resources/index.md b/doc-tool/resources/index.md
new file mode 100644
index 000000000..82f1d9cfc
--- /dev/null
+++ b/doc-tool/resources/index.md
@@ -0,0 +1,5 @@
+---
+layout: main
+---
+
+Hello, world!
diff --git a/doc-tool/resources/js/highlight.pack.js b/doc-tool/resources/js/highlight.pack.js
new file mode 100644
index 000000000..8d91f409b
--- /dev/null
+++ b/doc-tool/resources/js/highlight.pack.js
@@ -0,0 +1,2 @@
+/*! highlight.js v9.9.0 | BSD3 License | git.io/hljslicense */
+!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function i(e){return k.test(e)}function a(e){var n,t,r,a,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return R(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(a=o[n],i(a)||R(a))return a}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,i){for(var a=e.firstChild;a;a=a.nextSibling)3===a.nodeType?i+=a.nodeValue.length:1===a.nodeType&&(n.push({event:"start",offset:i,node:a}),i=r(a,i),t(a).match(/br|hr|img|input/)||n.push({event:"stop",offset:i,node:a}));return i}(e,0),n}function c(e,r,i){function a(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:"start"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value)+'"'}l+="<"+t(e)+w.map.call(e.attributes,r).join("")+">"}function u(e){l+="</"+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=a();if(l+=n(i.substring(s,g[0].offset)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=a();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(i.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(i,a){if(!i.compiled){if(i.compiled=!0,i.k=i.k||i.bK,i.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof i.k?c("keyword",i.k):E(i.k).forEach(function(e){c(e,i.k[e])}),i.k=u}i.lR=t(i.l||/\w+/,!0),a&&(i.bK&&(i.b="\\b("+i.bK.split(" ").join("|")+")\\b"),i.b||(i.b=/\B|\b/),i.bR=t(i.b),i.e||i.eW||(i.e=/\B|\b/),i.e&&(i.eR=t(i.e)),i.tE=n(i.e)||"",i.eW&&a.tE&&(i.tE+=(i.e?"|":"")+a.tE)),i.i&&(i.iR=t(i.i)),null==i.r&&(i.r=1),i.c||(i.c=[]);var s=[];i.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"===e?i:e)}),i.c=s,i.c.forEach(function(e){r(e,i)}),i.starts&&r(i.starts,a);var l=i.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([i.tE,i.i]).map(n).filter(Boolean);i.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function l(e,t,i,a){function o(e,n){var t,i;for(t=0,i=n.c.length;i>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!i&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var i=r?"":y.classPrefix,a='<span class="'+i,o=t?"":C;return a+=e+'">',a+n+o}function p(){var e,t,r,i;if(!E.k)return n(B);for(i="",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)i+=n(B.substring(t,r.index)),e=g(E,r),e?(M+=e[1],i+=h(e[0],n(r[0]))):i+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return i+n(B.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=""}function v(e){k+=e.cN?h(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var i=E;i.skip?B+=n:(i.rE||i.eE||(B+=n),b(),i.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),i.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"<unnamed>")+'"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var w,E=a||N,L={},k="";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,"",!0)+k);var B="",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substring(O,I.index),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},i=r;return t.filter(R).forEach(function(n){var t=l(n,e,!1);t.language=n,t.r>i.r&&(i=t),t.r>r.r&&(i=r,r=t)}),i.language&&(r.second_best=i),r}function g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&"\n"===e?"<br>":y.tabReplace?n.replace(/\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,i=[e.trim()];return e.match(/\bhljs\b/)||i.push("hljs"),-1===e.indexOf(r)&&i.push(r),i.join(" ").trim()}function p(e){var n,t,r,o,s,p=a(e);i(p)||(y.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");w.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||"").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="</span>",y={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},I={"&":"&amp;","<":"&lt;",">":"&gt;"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var i=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return i.c.push(e.PWM),i.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),i},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("scala",function(e){var t={cN:"meta",b:"@[A-Za-z]+"},a={cN:"subst",v:[{b:"\\$[A-Za-z0-9_]+"},{b:"\\${",e:"}"}]},r={cN:"string",v:[{b:'"',e:'"',i:"\\n",c:[e.BE]},{b:'"""',e:'"""',r:10},{b:'[a-z]+"',e:'"',i:"\\n",c:[e.BE,a]},{cN:"string",b:'[a-z]+"""',e:'"""',c:[a],r:10}]},c={cN:"symbol",b:"'\\w[\\w\\d_]*(?!')"},i={cN:"type",b:"\\b[A-Z][A-Za-z0-9_]*",r:0},s={cN:"title",b:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,r:0},n={cN:"class",bK:"class object trait type",e:/[:={\[\n;]/,eE:!0,c:[{bK:"extends with",r:10},{b:/\[/,e:/\]/,eB:!0,eE:!0,r:0,c:[i]},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,r:0,c:[i]},s]},l={cN:"function",bK:"def",e:/[:={\[(\n;]/,eE:!0,c:[s]};return{k:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},c:[e.CLCM,e.CBCM,r,c,i,l,n,e.CNM,t]}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+"|unless)\\s*",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",u="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",w=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+u+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(w).concat(d)}});hljs.registerLanguage("yaml",function(e){var a={literal:"{ } true false yes no Yes No True False null"},b="^[ \\-]*",r="[a-zA-Z_][\\w\\-]*",t={cN:"attr",v:[{b:b+r+":"},{b:b+'"'+r+'":'},{b:b+"'"+r+"':"}]},c={cN:"template-variable",v:[{b:"{{",e:"}}"},{b:"%{",e:"}"}]},l={cN:"string",r:0,v:[{b:/'/,e:/'/},{b:/"/,e:/"/}],c:[e.BE,c]};return{cI:!0,aliases:["yml","YAML","yaml"],c:[t,{cN:"meta",b:"^---s*$",r:10},{cN:"string",b:"[\\|>] *$",rE:!0,c:l.c,e:t.v[0].b},{b:"<%[%=-]?",e:"[%-]?%>",sL:"ruby",eB:!0,eE:!0,r:0},{cN:"type",b:"!!"+e.UIR},{cN:"meta",b:"&"+e.UIR+"$"},{cN:"meta",b:"\\*"+e.UIR+"$"},{cN:"bullet",b:"^ *-",r:0},l,e.HCM,e.CNM],k:a}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("bnf",function(e){return{c:[{cN:"attribute",b:/</,e:/>/},{b:/::=/,starts:{e:/$/,c:[{b:/</,e:/>/},e.CLCM,e.CBCM,e.ASM,e.QSM]}}]}});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/</,r:0,c:[{cN:"attr",b:e,r:0},{b:/=\s*/,r:0,c:[{cN:"string",endsParent:!0,v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s"'=<>`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("<!--","-->",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{name:"style"},c:[t],starts:{e:"</style>",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{name:"script"},c:[t],starts:{e:"</script>",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("htmlbars",function(e){var a="action collection component concat debugger each each-in else get hash if input link-to loc log mut outlet partial query-params render textarea unbound unless with yield view",t={i:/\}\}/,b:/[a-zA-Z0-9_]+=/,rB:!0,r:0,c:[{cN:"attr",b:/[a-zA-Z0-9_]+/}]},i=({i:/\}\}/,b:/\)/,e:/\)/,c:[{b:/[a-zA-Z\.\-]+/,k:{built_in:a},starts:{eW:!0,r:0,c:[e.QSM]}}]},{eW:!0,r:0,k:{keyword:"as",built_in:a},c:[e.QSM,t,e.NM]});return{cI:!0,sL:"xml",c:[e.C("{{!(--)?","(--)?}}"),{cN:"template-tag",b:/\{\{[#\/]/,e:/\}\}/,c:[{cN:"name",b:/[a-zA-Z\.\-]+/,k:{"builtin-name":a},starts:i}]},{cN:"template-variable",b:/\{\{[a-zA-Z][a-zA-Z\-]+/,e:/\}\}/,k:{keyword:"as",built_in:a},c:[e.QSM]}]}});hljs.registerLanguage("rust",function(e){var t="([uif](8|16|32|64|size))?",r="alignof as be box break const continue crate do else enum extern false fn for if impl in let loop match mod mut offsetof once priv proc pub pure ref return self Self sizeof static struct super trait true type typeof unsafe unsized use virtual while where yield move default int i8 i16 i32 i64 isize uint u8 u32 u64 usize float f32 f64 str char bool",n="Copy Send Sized Sync Drop Fn FnMut FnOnce drop Box ToOwned Clone PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator Option Result SliceConcatExt String ToString Vec assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules!";return{aliases:["rs"],k:{keyword:r,literal:"true false Some None Ok Err",built_in:n},l:e.IR+"!?",i:"</",c:[e.CLCM,e.C("/\\*","\\*/",{c:["self"]}),e.inherit(e.QSM,{b:/b?"/,i:null}),{cN:"string",v:[{b:/r(#*)".*?"\1(?!#)/},{b:/b?'\\?(x\w{2}|u\w{4}|U\w{8}|.)'/}]},{cN:"symbol",b:/'[a-zA-Z_][a-zA-Z0-9_]*/},{cN:"number",v:[{b:"\\b0b([01_]+)"+t},{b:"\\b0o([0-7_]+)"+t},{b:"\\b0x([A-Fa-f0-9_]+)"+t},{b:"\\b(\\d[\\d_]*(\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)"+t}],r:0},{cN:"function",bK:"fn",e:"(\\(|<)",eE:!0,c:[e.UTM]},{cN:"meta",b:"#\\!?\\[",e:"\\]",c:[{cN:"meta-string",b:/"/,e:/"/}]},{cN:"class",bK:"type",e:";",c:[e.inherit(e.UTM,{endsParent:!0})],i:"\\S"},{cN:"class",bK:"trait enum struct",e:"{",c:[e.inherit(e.UTM,{endsParent:!0})],i:"[\\w\\d]"},{b:e.IR+"::",k:{built_in:n}},{b:"->"}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b:/</,e:/(\/\w+|\w+\/)>/,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("coq",function(e){return{k:{keyword:"_ as at cofix else end exists exists2 fix for forall fun if IF in let match mod Prop return Set then Type using where with Abort About Add Admit Admitted All Arguments Assumptions Axiom Back BackTo Backtrack Bind Blacklist Canonical Cd Check Class Classes Close Coercion Coercions CoFixpoint CoInductive Collection Combined Compute Conjecture Conjectures Constant constr Constraint Constructors Context Corollary CreateHintDb Cut Declare Defined Definition Delimit Dependencies DependentDerive Drop eauto End Equality Eval Example Existential Existentials Existing Export exporting Extern Extract Extraction Fact Field Fields File Fixpoint Focus for From Function Functional Generalizable Global Goal Grab Grammar Graph Guarded Heap Hint HintDb Hints Hypotheses Hypothesis ident Identity If Immediate Implicit Import Include Inductive Infix Info Initial Inline Inspect Instance Instances Intro Intros Inversion Inversion_clear Language Left Lemma Let Libraries Library Load LoadPath Local Locate Ltac ML Mode Module Modules Monomorphic Morphism Next NoInline Notation Obligation Obligations Opaque Open Optimize Options Parameter Parameters Parametric Path Paths pattern Polymorphic Preterm Print Printing Program Projections Proof Proposition Pwd Qed Quit Rec Record Recursive Redirect Relation Remark Remove Require Reserved Reset Resolve Restart Rewrite Right Ring Rings Save Scheme Scope Scopes Script Search SearchAbout SearchHead SearchPattern SearchRewrite Section Separate Set Setoid Show Solve Sorted Step Strategies Strategy Structure SubClass Table Tables Tactic Term Test Theorem Time Timeout Transparent Type Typeclasses Types Undelimit Undo Unfocus Unfocused Unfold Universe Universes Unset Unshelve using Variable Variables Variant Verbose Visibility where with",built_in:"abstract absurd admit after apply as assert assumption at auto autorewrite autounfold before bottom btauto by case case_eq cbn cbv change classical_left classical_right clear clearbody cofix compare compute congruence constr_eq constructor contradict contradiction cut cutrewrite cycle decide decompose dependent destruct destruction dintuition discriminate discrR do double dtauto eapply eassumption eauto ecase econstructor edestruct ediscriminate eelim eexact eexists einduction einjection eleft elim elimtype enough equality erewrite eright esimplify_eq esplit evar exact exactly_once exfalso exists f_equal fail field field_simplify field_simplify_eq first firstorder fix fold fourier functional generalize generalizing gfail give_up has_evar hnf idtac in induction injection instantiate intro intro_pattern intros intuition inversion inversion_clear is_evar is_var lapply lazy left lia lra move native_compute nia nsatz omega once pattern pose progress proof psatz quote record red refine reflexivity remember rename repeat replace revert revgoals rewrite rewrite_strat right ring ring_simplify rtauto set setoid_reflexivity setoid_replace setoid_rewrite setoid_symmetry setoid_transitivity shelve shelve_unifiable simpl simple simplify_eq solve specialize split split_Rabs split_Rmult stepl stepr subst sum swap symmetry tactic tauto time timeout top transitivity trivial try tryif unfold unify until using vm_compute with"},c:[e.QSM,e.C("\\(\\*","\\*\\)"),e.CNM,{cN:"type",eB:!0,b:"\\|\\s*",e:"\\w+"},{b:/[-=]>/}]}});hljs.registerLanguage("tex",function(c){var e={cN:"tag",b:/\\/,r:0,c:[{cN:"name",v:[{b:/[a-zA-Zа-яА-я]+[*]?/},{b:/[^a-zA-Zа-яА-я0-9]/}],starts:{eW:!0,r:0,c:[{cN:"string",v:[{b:/\[/,e:/\]/},{b:/\{/,e:/\}/}]},{b:/\s*=\s*/,eW:!0,r:0,c:[{cN:"number",b:/-?\d*\.?\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?/}]}]}}]};return{c:[e,{cN:"formula",c:[e],r:0,v:[{b:/\$\$/,e:/\$\$/},{b:/\$/,e:/\$/}]},c.C("%","$",{r:0})]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("scss",function(e){var t="[a-zA-Z-][a-zA-Z0-9_-]*",i={cN:"variable",b:"(\\$"+t+")\\b"},r={cN:"number",b:"#[0-9A-Fa-f]+"};({cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:!0,i:"[^\\s]",starts:{eW:!0,eE:!0,c:[r,e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"meta",b:"!important"}]}});return{cI:!0,i:"[=/|']",c:[e.CLCM,e.CBCM,{cN:"selector-id",b:"\\#[A-Za-z0-9_-]+",r:0},{cN:"selector-class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"selector-attr",b:"\\[",e:"\\]",i:"$"},{cN:"selector-tag",b:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",r:0},{b:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{b:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},i,{cN:"attribute",b:"\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",i:"[^\\s]"},{b:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{b:":",e:";",c:[i,r,e.CSSNM,e.QSM,e.ASM,{cN:"meta",b:"!important"}]},{b:"@",e:"[{;]",k:"mixin include extend for if else each while charset import debug media page content font-face namespace warn",c:[i,e.QSM,e.ASM,r,e.CSSNM,{b:"\\s[A-Za-z0-9_.-]+",r:0}]}]}});hljs.registerLanguage("python",function(e){var r={cN:"meta",b:/^(>>>|\.\.\.) /},b={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]},a={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},l={cN:"params",b:/\(/,e:/\)/,c:["self",r,a,b]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)|=>/,c:[r,a,b,e.HCM,{v:[{cN:"function",bK:"def"},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,l,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"section",b:/^[\w]+:\s*$/},{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("haskell",function(e){var i={v:[e.C("--","$"),e.C("{-","-}",{c:["self"]})]},a={cN:"meta",b:"{-#",e:"#-}"},l={cN:"meta",b:"^#",e:"$"},c={cN:"type",b:"\\b[A-Z][\\w']*",r:0},n={b:"\\(",e:"\\)",i:'"',c:[a,l,{cN:"type",b:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},e.inherit(e.TM,{b:"[_a-z][\\w']*"}),i]},s={b:"{",e:"}",c:n.c};return{aliases:["hs"],k:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",c:[{bK:"module",e:"where",k:"module where",c:[n,i],i:"\\W\\.|;"},{b:"\\bimport\\b",e:"$",k:"import qualified as hiding",c:[n,i],i:"\\W\\.|;"},{cN:"class",b:"^(\\s*)?(class|instance)\\b",e:"where",k:"class family instance where",c:[c,n,i]},{cN:"class",b:"\\b(data|(new)?type)\\b",e:"$",k:"data family type newtype deriving",c:[a,c,n,s,i]},{bK:"default",e:"$",c:[c,n,i]},{bK:"infix infixl infixr",e:"$",c:[e.CNM,i]},{b:"\\bforeign\\b",e:"$",k:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",c:[c,e.QSM,i]},{cN:"meta",b:"#!\\/usr\\/bin\\/env runhaskell",e:"$"},a,l,e.QSM,e.CNM,c,e.inherit(e.TM,{b:"^[_a-z][\\w']*"}),i,{b:"->|<-"}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("java",function(e){var a="[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",t=a+"(<"+a+"(\\s*,\\s*"+a+")*>)?",r="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",s="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",c={cN:"number",b:s,r:0};return{aliases:["jsp"],k:r,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},c,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("handlebars",function(e){var a={"builtin-name":"each in with if else unless bindattr action collection debugger log outlet template unbound view yield"};return{aliases:["hbs","html.hbs","html.handlebars"],cI:!0,sL:"xml",c:[e.C("{{!(--)?","(--)?}}"),{cN:"template-tag",b:/\{\{[#\/]/,e:/\}\}/,c:[{cN:"name",b:/[a-zA-Z\.-]+/,k:a,starts:{eW:!0,r:0,c:[e.QSM]}}]},{cN:"template-variable",b:/\{\{/,e:/\}\}/,k:a}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("vim",function(e){return{l:/[!#@\w]+/,k:{keyword:"N|0 P|0 X|0 a|0 ab abc abo al am an|0 ar arga argd arge argdo argg argl argu as au aug aun b|0 bN ba bad bd be bel bf bl bm bn bo bp br brea breaka breakd breakl bro bufdo buffers bun bw c|0 cN cNf ca cabc caddb cad caddf cal cat cb cc ccl cd ce cex cf cfir cgetb cgete cg changes chd che checkt cl cla clo cm cmapc cme cn cnew cnf cno cnorea cnoreme co col colo com comc comp con conf cope cp cpf cq cr cs cst cu cuna cunme cw delm deb debugg delc delf dif diffg diffo diffp diffpu diffs diffthis dig di dl dell dj dli do doautoa dp dr ds dsp e|0 ea ec echoe echoh echom echon el elsei em en endfo endf endt endw ene ex exe exi exu f|0 files filet fin fina fini fir fix fo foldc foldd folddoc foldo for fu go gr grepa gu gv ha helpf helpg helpt hi hid his ia iabc if ij il im imapc ime ino inorea inoreme int is isp iu iuna iunme j|0 ju k|0 keepa kee keepj lN lNf l|0 lad laddb laddf la lan lat lb lc lch lcl lcs le lefta let lex lf lfir lgetb lgete lg lgr lgrepa lh ll lla lli lmak lm lmapc lne lnew lnf ln loadk lo loc lockv lol lope lp lpf lr ls lt lu lua luad luaf lv lvimgrepa lw m|0 ma mak map mapc marks mat me menut mes mk mks mksp mkv mkvie mod mz mzf nbc nb nbs new nm nmapc nme nn nnoreme noa no noh norea noreme norm nu nun nunme ol o|0 om omapc ome on ono onoreme opt ou ounme ow p|0 profd prof pro promptr pc ped pe perld po popu pp pre prev ps pt ptN ptf ptj ptl ptn ptp ptr pts pu pw py3 python3 py3d py3f py pyd pyf quita qa rec red redi redr redraws reg res ret retu rew ri rightb rub rubyd rubyf rund ru rv sN san sa sal sav sb sbN sba sbf sbl sbm sbn sbp sbr scrip scripte scs se setf setg setl sf sfir sh sim sig sil sl sla sm smap smapc sme sn sni sno snor snoreme sor so spelld spe spelli spellr spellu spellw sp spr sre st sta startg startr star stopi stj sts sun sunm sunme sus sv sw sy synti sync tN tabN tabc tabdo tabe tabf tabfir tabl tabm tabnew tabn tabo tabp tabr tabs tab ta tags tc tcld tclf te tf th tj tl tm tn to tp tr try ts tu u|0 undoj undol una unh unl unlo unm unme uns up ve verb vert vim vimgrepa vi viu vie vm vmapc vme vne vn vnoreme vs vu vunme windo w|0 wN wa wh wi winc winp wn wp wq wqa ws wu wv x|0 xa xmapc xm xme xn xnoreme xu xunme y|0 z|0 ~ Next Print append abbreviate abclear aboveleft all amenu anoremenu args argadd argdelete argedit argglobal arglocal argument ascii autocmd augroup aunmenu buffer bNext ball badd bdelete behave belowright bfirst blast bmodified bnext botright bprevious brewind break breakadd breakdel breaklist browse bunload bwipeout change cNext cNfile cabbrev cabclear caddbuffer caddexpr caddfile call catch cbuffer cclose center cexpr cfile cfirst cgetbuffer cgetexpr cgetfile chdir checkpath checktime clist clast close cmap cmapclear cmenu cnext cnewer cnfile cnoremap cnoreabbrev cnoremenu copy colder colorscheme command comclear compiler continue confirm copen cprevious cpfile cquit crewind cscope cstag cunmap cunabbrev cunmenu cwindow delete delmarks debug debuggreedy delcommand delfunction diffupdate diffget diffoff diffpatch diffput diffsplit digraphs display deletel djump dlist doautocmd doautoall deletep drop dsearch dsplit edit earlier echo echoerr echohl echomsg else elseif emenu endif endfor endfunction endtry endwhile enew execute exit exusage file filetype find finally finish first fixdel fold foldclose folddoopen folddoclosed foldopen function global goto grep grepadd gui gvim hardcopy help helpfind helpgrep helptags highlight hide history insert iabbrev iabclear ijump ilist imap imapclear imenu inoremap inoreabbrev inoremenu intro isearch isplit iunmap iunabbrev iunmenu join jumps keepalt keepmarks keepjumps lNext lNfile list laddexpr laddbuffer laddfile last language later lbuffer lcd lchdir lclose lcscope left leftabove lexpr lfile lfirst lgetbuffer lgetexpr lgetfile lgrep lgrepadd lhelpgrep llast llist lmake lmap lmapclear lnext lnewer lnfile lnoremap loadkeymap loadview lockmarks lockvar lolder lopen lprevious lpfile lrewind ltag lunmap luado luafile lvimgrep lvimgrepadd lwindow move mark make mapclear match menu menutranslate messages mkexrc mksession mkspell mkvimrc mkview mode mzscheme mzfile nbclose nbkey nbsart next nmap nmapclear nmenu nnoremap nnoremenu noautocmd noremap nohlsearch noreabbrev noremenu normal number nunmap nunmenu oldfiles open omap omapclear omenu only onoremap onoremenu options ounmap ounmenu ownsyntax print profdel profile promptfind promptrepl pclose pedit perl perldo pop popup ppop preserve previous psearch ptag ptNext ptfirst ptjump ptlast ptnext ptprevious ptrewind ptselect put pwd py3do py3file python pydo pyfile quit quitall qall read recover redo redir redraw redrawstatus registers resize retab return rewind right rightbelow ruby rubydo rubyfile rundo runtime rviminfo substitute sNext sandbox sargument sall saveas sbuffer sbNext sball sbfirst sblast sbmodified sbnext sbprevious sbrewind scriptnames scriptencoding scscope set setfiletype setglobal setlocal sfind sfirst shell simalt sign silent sleep slast smagic smapclear smenu snext sniff snomagic snoremap snoremenu sort source spelldump spellgood spellinfo spellrepall spellundo spellwrong split sprevious srewind stop stag startgreplace startreplace startinsert stopinsert stjump stselect sunhide sunmap sunmenu suspend sview swapname syntax syntime syncbind tNext tabNext tabclose tabedit tabfind tabfirst tablast tabmove tabnext tabonly tabprevious tabrewind tag tcl tcldo tclfile tearoff tfirst throw tjump tlast tmenu tnext topleft tprevious trewind tselect tunmenu undo undojoin undolist unabbreviate unhide unlet unlockvar unmap unmenu unsilent update vglobal version verbose vertical vimgrep vimgrepadd visual viusage view vmap vmapclear vmenu vnew vnoremap vnoremenu vsplit vunmap vunmenu write wNext wall while winsize wincmd winpos wnext wprevious wqall wsverb wundo wviminfo xit xall xmapclear xmap xmenu xnoremap xnoremenu xunmap xunmenu yank",built_in:"synIDtrans atan2 range matcharg did_filetype asin feedkeys xor argv complete_check add getwinposx getqflist getwinposy screencol clearmatches empty extend getcmdpos mzeval garbagecollect setreg ceil sqrt diff_hlID inputsecret get getfperm getpid filewritable shiftwidth max sinh isdirectory synID system inputrestore winline atan visualmode inputlist tabpagewinnr round getregtype mapcheck hasmapto histdel argidx findfile sha256 exists toupper getcmdline taglist string getmatches bufnr strftime winwidth bufexists strtrans tabpagebuflist setcmdpos remote_read printf setloclist getpos getline bufwinnr float2nr len getcmdtype diff_filler luaeval resolve libcallnr foldclosedend reverse filter has_key bufname str2float strlen setline getcharmod setbufvar index searchpos shellescape undofile foldclosed setqflist buflisted strchars str2nr virtcol floor remove undotree remote_expr winheight gettabwinvar reltime cursor tabpagenr finddir localtime acos getloclist search tanh matchend rename gettabvar strdisplaywidth type abs py3eval setwinvar tolower wildmenumode log10 spellsuggest bufloaded synconcealed nextnonblank server2client complete settabwinvar executable input wincol setmatches getftype hlID inputsave searchpair or screenrow line settabvar histadd deepcopy strpart remote_peek and eval getftime submatch screenchar winsaveview matchadd mkdir screenattr getfontname libcall reltimestr getfsize winnr invert pow getbufline byte2line soundfold repeat fnameescape tagfiles sin strwidth spellbadword trunc maparg log lispindent hostname setpos globpath remote_foreground getchar synIDattr fnamemodify cscope_connection stridx winbufnr indent min complete_add nr2char searchpairpos inputdialog values matchlist items hlexists strridx browsedir expand fmod pathshorten line2byte argc count getwinvar glob foldtextresult getreg foreground cosh matchdelete has char2nr simplify histget searchdecl iconv winrestcmd pumvisible writefile foldlevel haslocaldir keys cos matchstr foldtext histnr tan tempname getcwd byteidx getbufvar islocked escape eventhandler remote_send serverlist winrestview synstack pyeval prevnonblank readfile cindent filereadable changenr exp"},i:/;/,c:[e.NM,e.ASM,{cN:"string",b:/"(\\"|\n\\|[^"\n])*"/},e.C('"',"$"),{cN:"variable",b:/[bwtglsav]:[\w\d_]*/},{cN:"function",bK:"function function!",e:"$",r:0,c:[e.TM,{cN:"params",b:"\\(",e:"\\)"}]},{cN:"symbol",b:/<[\w-]+>/}]}});hljs.registerLanguage("ebnf",function(a){var e=a.C(/\(\*/,/\*\)/),t={cN:"attribute",b:/^[ ]*[a-zA-Z][a-zA-Z-]*([\s-]+[a-zA-Z][a-zA-Z]*)*/},r={cN:"meta",b:/\?.*\?/},b={b:/=/,e:/;/,c:[e,r,a.ASM,a.QSM]};return{i:/\S/,c:[e,t,b]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("kotlin",function(e){var t={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline interface annotation data sealed internal infix operator out by constructor super trait volatile transient native default",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},r={cN:"keyword",b:/\b(break|continue|return|this)\b/,starts:{c:[{cN:"symbol",b:/@\w+/}]}},n={cN:"symbol",b:e.UIR+"@"},i={cN:"subst",v:[{b:"\\$"+e.UIR},{b:"\\${",e:"}",c:[e.ASM,e.CNM]}]},a={cN:"string",v:[{b:'"""',e:'"""',c:[i]},{b:"'",e:"'",i:/\n/,c:[e.BE]},{b:'"',e:'"',i:/\n/,c:[e.BE,i]}]},c={cN:"meta",b:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UIR+")?"},s={cN:"meta",b:"@"+e.UIR,c:[{b:/\(/,e:/\)/,c:[e.inherit(a,{cN:"meta-string"})]}]};return{k:t,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,r,n,c,s,{cN:"function",bK:"fun",e:"[(]|$",rB:!0,eE:!0,k:t,i:/fun\s+(<.*>)?[^\s\(]+(\s+[^\s\(]+)\s*=/,r:5,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"type",b:/</,e:/>/,k:"reified",r:0},{cN:"params",b:/\(/,e:/\)/,endsParent:!0,k:t,r:0,c:[{b:/:/,e:/[=,\/]/,eW:!0,c:[{cN:"type",b:e.UIR},e.CLCM,e.CBCM],r:0},e.CLCM,e.CBCM,c,s,a,e.CNM]},e.CBCM]},{cN:"class",bK:"class interface trait",e:/[:\{(]|$/,eE:!0,i:"extends implements",c:[{bK:"public protected internal private constructor"},e.UTM,{cN:"type",b:/</,e:/>/,eB:!0,eE:!0,r:0},{cN:"type",b:/[,:]\s*/,e:/[<\(,]|$/,eB:!0,rE:!0},c,s]},a,{cN:"meta",b:"^#!/usr/bin/env",e:"$",i:"\n"},e.CNM]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\._]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("dockerfile",function(e){return{aliases:["docker"],cI:!0,k:"from maintainer expose env user onbuild",c:[e.HCM,e.ASM,e.QSM,e.NM,{bK:"run cmd entrypoint volume add copy workdir label healthcheck",starts:{e:/[^\\]\n/,sL:"bash"}}],i:"</"}}); \ No newline at end of file
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
new file mode 100644
index 000000000..708c26cc0
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
@@ -0,0 +1,37 @@
+package dotty.tools
+package dottydoc
+
+import core._
+import core.transform._
+import dotc.core.Phases.Phase
+import dotc.Compiler
+
+/** Custom Compiler with phases for the documentation tool
+ *
+ * The idea here is to structure `dottydoc` around the new infrastructure. As
+ * such, dottydoc will itself be a compiler. It will, however, produce a format
+ * that can be used by other tools or web-browsers.
+ *
+ * Example:
+ * 1. Use the existing FrontEnd to typecheck the code being fed to dottydoc,
+ * wihtout discarding AnyVal interfaces
+ * 2. Create an AST that is serializable
+ * 3. Serialize to JS object
+ */
+class DocCompiler extends Compiler {
+ override def phases: List[List[Phase]] = List(
+ List(new DocFrontEnd),
+ List(new DocImplicitsPhase),
+ List(new DocASTPhase),
+ List(DocMiniTransformations(new UsecasePhase,
+ new DocstringPhase,
+ new PackageObjectsPhase,
+ new LinkReturnTypes,
+ new LinkParamListTypes,
+ new LinkImplicitlyAddedTypes,
+ new LinkSuperTypes,
+ new LinkCompanions,
+ new AlternateConstructors,
+ new SortMembers))
+ )
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
new file mode 100644
index 000000000..515de9ae9
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
@@ -0,0 +1,59 @@
+package dotty.tools
+package dottydoc
+
+import dotty.tools.dottydoc.util.syntax._
+import core.ContextDottydoc
+import dotc.core.Contexts._
+import dotc.{ Compiler, Driver }
+import model.Package
+import dotc.config._
+import dotc.core.Comments.ContextDoc
+import staticsite.Site
+
+/** `DocDriver` implements the main entry point to the Dotty documentation
+ * tool. It's methods are used by the external scala and java APIs.
+ */
+class DocDriver extends Driver {
+ import java.util.{ Map => JMap }
+ import model.JavaConverters._
+
+ override def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
+ val ctx = rootCtx.fresh
+ val summary = CompilerCommand.distill(args)(ctx)
+
+ ctx.setSettings(summary.sstate)
+ ctx.setSetting(ctx.settings.YkeepComments, true)
+ ctx.setSetting(ctx.settings.YnoInline, true)
+ ctx.setProperty(ContextDoc, new ContextDottydoc)
+
+ val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx)
+ (fileNames, ctx)
+ }
+
+ override def newCompiler(implicit ctx: Context): Compiler = new DocCompiler
+
+ def compiledDocs(args: Array[String]): collection.Map[String, Package] = {
+ val (fileNames, ctx) = setup(args, initCtx.fresh)
+ doCompile(newCompiler(ctx), fileNames)(ctx)
+
+ ctx.docbase.packages
+ }
+
+ override def main(args: Array[String]): Unit = {
+ implicit val (filesToDocument, ctx) = setup(args, initCtx.fresh)
+ val reporter = doCompile(newCompiler(ctx), filesToDocument)(ctx)
+ val siteRoot = new java.io.File(ctx.settings.siteRoot.value)
+
+ if (!siteRoot.exists || !siteRoot.isDirectory)
+ ctx.error(s"Site root does not exist: $siteRoot")
+ else {
+ Site(siteRoot, ctx.settings.projectName.value, ctx.docbase.packages)
+ .generateApiDocs()
+ .copyStaticFiles()
+ .generateHtmlFiles()
+ .generateBlog()
+
+ System.exit(if (reporter.hasErrors) 1 else 0)
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocFrontEnd.scala b/doc-tool/src/dotty/tools/dottydoc/DocFrontEnd.scala
new file mode 100644
index 000000000..606fd0fc6
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/DocFrontEnd.scala
@@ -0,0 +1,17 @@
+package dotty.tools
+package dottydoc
+
+import dotc.typer.FrontEnd
+import dotc.core.Contexts.Context
+import dotc.CompilationUnit
+
+/** `DocFrontEnd` uses the Dotty `FrontEnd` without discarding the AnyVal
+ * interfaces for Boolean, Int, Char, Long, Byte etc.
+ *
+ * It currently still throws away Java sources by overriding
+ * `discardAfterTyper`.
+ */
+class DocFrontEnd extends FrontEnd {
+ override protected def discardAfterTyper(unit: CompilationUnit)(implicit ctx: Context) =
+ unit.isJava
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DottyDoc.scala b/doc-tool/src/dotty/tools/dottydoc/DottyDoc.scala
deleted file mode 100644
index 0dea96134..000000000
--- a/doc-tool/src/dotty/tools/dottydoc/DottyDoc.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package dotty.tools
-package dottydoc
-
-import dotty.tools.dottydoc.util.syntax._
-import core._
-import core.transform._
-import dotc.config.CompilerCommand
-import dotc.config.Printers.dottydoc
-import dotc.core.Contexts._
-import dotc.core.Comments.ContextDoc
-import dotc.core.Phases.Phase
-import dotc.typer.FrontEnd
-import dotc.{ CompilationUnit, Compiler, Driver, Run }
-import io.PlainFile
-import model.Package
-import model.json._
-
-import _root_.java.util.{ Map => JMap }
-
-/** Custom Compiler with phases for the documentation tool
- *
- * The idea here is to structure `dottydoc` around the new infrastructure. As
- * such, dottydoc will itself be a compiler. It will, however, produce a format
- * that can be used by other tools or web-browsers.
- *
- * Example:
- * 1. Use the existing FrontEnd to typecheck the code being fed to dottydoc
- * 2. Create an AST that is serializable
- * 3. Serialize to JS object
- */
-class DocCompiler extends Compiler {
- override def phases: List[List[Phase]] = List(
- List(new DocFrontEnd),
- List(new DocImplicitsPhase),
- List(new DocASTPhase),
- List(DocMiniTransformations(new UsecasePhase,
- new DocstringPhase,
- new LinkReturnTypes,
- new LinkParamListTypes,
- new LinkImplicitlyAddedTypes,
- new LinkSuperTypes,
- new AlternateConstructors,
- new SortMembers))
- )
-}
-
-class DocFrontEnd extends FrontEnd {
- override protected def discardAfterTyper(unit: CompilationUnit)(implicit ctx: Context) =
- unit.isJava
-}
-
-abstract class DocDriver extends Driver {
- import scala.collection.JavaConverters._
-
- override def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
- val ctx = rootCtx.fresh
- val summary = CompilerCommand.distill(args)(ctx)
-
- ctx.setSettings(summary.sstate)
- ctx.setSetting(ctx.settings.YkeepComments, true)
- ctx.setProperty(ContextDoc, new ContextDottydoc)
-
- val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx)
- (fileNames, ctx)
- }
-
- override def newCompiler(implicit ctx: Context): Compiler = new DocCompiler
-
- def compiledDocs(args: Array[String]): collection.Map[String, Package] = {
- val (fileNames, ctx) = setup(args, initCtx.fresh)
- doCompile(newCompiler(ctx), fileNames)(ctx)
-
- ctx.docbase.packages
- }
-
- def compiledDocsJava(args: Array[String]): JMap[String, Package] =
- compiledDocs(args).asJava
-
- def indexToJson(index: collection.Map[String, Package]): String =
- index.json
-
- def indexToJsonJava(index: JMap[String, Package]): String =
- indexToJson(index.asScala)
-}
diff --git a/doc-tool/src/dotty/tools/dottydoc/Main.scala b/doc-tool/src/dotty/tools/dottydoc/Main.scala
new file mode 100644
index 000000000..f158bdbfc
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/Main.scala
@@ -0,0 +1,5 @@
+package dotty.tools
+package dottydoc
+
+/** Main runnable for DottyDoc */
+object Main extends DocDriver
diff --git a/doc-tool/src/dotty/tools/dottydoc/api/java/Dottydoc.java b/doc-tool/src/dotty/tools/dottydoc/api/java/Dottydoc.java
deleted file mode 100644
index 1bdfe0488..000000000
--- a/doc-tool/src/dotty/tools/dottydoc/api/java/Dottydoc.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package dotty.tools.dottydoc.api.java;
-
-import dotty.tools.dottydoc.DocDriver;
-import dotty.tools.dottydoc.model.Package;
-import dotty.tools.dottydoc.util.OutputWriter;
-import java.util.Map;
-import java.util.List;
-import java.net.URL;
-
-/**
- * The Dottydoc API is fairly simple. The tool creates an index by calling:
- * "createIndex" with the same argument list as you would the compiler - e.g:
- *
- * {{{
- * String[] array = {
- * "-language:Scala2"
- * };
- *
- * Map<String, Package> index = createIndex(array);
- * }}}
- *
- * Once the index has been generated, the tool can also build a documentation
- * API given a Mustache template and a flat resources structure (i.e. absolute
- * paths to each resource, which will be put in the same directory).
- *
- * {{{
- * buildDocs("path/to/output/dir", templateURL, resources, index);
- * }}}
- *
- * The tool can also generate JSON from the created index using "toJson(index)"
- * or directly using "createJsonIndex"
- */
-public class Dottydoc extends DocDriver {
-
- /** Creates index from compiler arguments */
- public Map<String, Package> createIndex(String[] args) {
- return compiledDocsJava(args);
- }
-
- /** Creates JSON from compiler arguments */
- public String createJsonIndex(String[] args) {
- return indexToJsonJava(createIndex(args));
- }
-
- public String toJson(Map<String, Package> index) {
- return indexToJsonJava(index);
- }
-
- /** Creates a documentation from the given parameters */
- public void buildDocs(
- String outputDir,
- URL template,
- List<URL> resources,
- Map<String, Package> index
- ) {
- new OutputWriter().writeJava(index, outputDir, template, resources);
- }
-
- /** Writes JSON to an output directory as "index.json" */
- public void writeJson(Map<String, Package> index, String outputDir) {
- new OutputWriter().writeJsonJava(index, outputDir);
- }
-}
diff --git a/doc-tool/src/dotty/tools/dottydoc/api/scala/Dottydoc.scala b/doc-tool/src/dotty/tools/dottydoc/api/scala/Dottydoc.scala
deleted file mode 100644
index 15db81a95..000000000
--- a/doc-tool/src/dotty/tools/dottydoc/api/scala/Dottydoc.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package dotty.tools.dottydoc.api.scala
-
-import dotty.tools.dottydoc.DocDriver
-import dotty.tools.dottydoc.model.Package
-import dotty.tools.dottydoc.util.OutputWriter
-
-import scala.collection.Map
-import java.net.URL
-
-/**
- * The Dottydoc API is fairly simple. The tool creates an index by calling:
- * "createIndex" with the same argument list as you would the compiler - e.g:
- *
- * {{{
- * val array: Array[String] = Array(
- * "-language:Scala2"
- * )
- *
- * val index: Map[String, Package] = createIndex(array)
- * }}}
- *
- * Once the index has been generated, the tool can also build a documentation
- * API given a Mustache template and a flat resources structure (i.e. absolute
- * paths to each resource, which will be put in the same directory).
- *
- * {{{
- * buildDocs("path/to/output/dir", templateURL, resources, index)
- * }}}
- *
- * The tool can also generate JSON from the created index using "indexToJson"
- * or directly using "createJsonIndex"
- */
-trait Dottydoc extends DocDriver {
- /** Creates index from compiler arguments */
- def createIndex(args: Array[String]): Map[String, Package] =
- compiledDocs(args)
-
- /** Creates JSON from compiler arguments */
- def createJsonIndex(args: Array[String]): String =
- indexToJson(compiledDocs(args))
-
- /** Creates a documentation from the given parameters */
- def buildDocs(outDir: String, template: URL, resources: List[URL], index: Map[String, Package]) =
- new OutputWriter().write(index, outDir, template, resources)
-
- /** Writes JSON to an output directory as "index.json" */
- def writeJson(index: Map[String, Package], outputDir: String) =
- new OutputWriter().writeJson(index, outputDir)
-}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
index c60038836..16f0776fa 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
@@ -6,6 +6,10 @@ import dotc.core.Symbols.Symbol
import dotc.core.Comments.ContextDocstrings
import model.Package
+import dotc.core.Contexts.Context
+import dotc.printing.Highlighting._
+import dotc.util.{ SourcePosition, NoSourcePosition }
+
class ContextDottydoc extends ContextDocstrings {
import scala.collection.mutable
@@ -20,4 +24,29 @@ class ContextDottydoc extends ContextDocstrings {
def addDef(s: Symbol, d: Symbol): Unit = _defs = (_defs + {
s -> _defs.get(s).map(xs => xs + d).getOrElse(Set(d))
})
+
+ def error(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit = ctx.error({
+ NoColor("[") + Red("doc error") + "] " + msg
+ }.toString, pos)
+
+ def error(msg: String)(implicit ctx: Context): Unit = error(msg, NoSourcePosition)
+
+ def warn(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit = ctx.warning({
+ NoColor("[") + Yellow("doc warn") + "] " + msg
+ }.toString, pos)
+
+ def warn(msg: String)(implicit ctx: Context): Unit = warn(msg, NoSourcePosition)
+
+ def echo(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit = ctx.echo({
+ "[doc info] " + msg
+ }.toString, pos)
+
+ def echo(msg: String)(implicit ctx: Context): Unit = echo(msg, NoSourcePosition)
+
+ def debug(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit =
+ if (ctx.settings.debug.value) ctx.inform({
+ "[doc debug] " + msg
+ }.toString, pos)
+
+ def debug(msg: String)(implicit ctx: Context): Unit = debug(msg, NoSourcePosition)
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
index 483c22984..460566838 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
@@ -23,21 +23,21 @@ class DocASTPhase extends Phase {
import util.traversing._
import util.internal.setters._
- def phaseName = "docphase"
+ def phaseName = "docASTPhase"
/** Build documentation hierarchy from existing tree */
- def collect(tree: Tree, prev: List[String] = Nil)(implicit ctx: Context): Entity = {
+ def collect(tree: Tree)(implicit ctx: Context): Entity = {
val implicitConversions = ctx.docbase.defs(tree.symbol)
- def collectList(xs: List[Tree], ps: List[String]): List[Entity] =
- xs.map(collect(_, ps)).filter(_ != NonEntity)
+ def collectList(xs: List[Tree]): List[Entity] =
+ xs.map(collect).filter(_ != NonEntity)
- def collectEntityMembers(xs: List[Tree], ps: List[String]) =
- collectList(xs, ps).asInstanceOf[List[Entity with Members]]
+ def collectEntityMembers(xs: List[Tree]) =
+ collectList(xs).asInstanceOf[List[Entity with Members]]
- def collectMembers(tree: Tree, ps: List[String] = prev)(implicit ctx: Context): List[Entity] = {
+ def collectMembers(tree: Tree)(implicit ctx: Context): List[Entity] = {
val defs = (tree match {
- case t: Template => collectList(t.body, ps)
+ case t: Template => collectList(t.body)
case _ => Nil
})
@@ -45,12 +45,13 @@ class DocASTPhase extends Phase {
}
def membersFromSymbol(sym: Symbol): List[Entity] = {
- if (sym.info ne NoType) {
+ if (sym.info.exists) {
val defs = sym.info.bounds.hi.finalResultType.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private)
.filterNot(_.symbol.owner.name.show == "Any")
.map { meth =>
DefImpl(
meth.symbol,
+ annotations(meth.symbol),
meth.symbol.name.show,
Nil,
path(meth.symbol),
@@ -61,12 +62,16 @@ class DocASTPhase extends Phase {
)
}.toList
- val vals = sym.info.fields.filterNot(_.symbol.is(Flags.Private | Flags.Synthetic)).map { value =>
+ // don't add privates, synthetics or class parameters (i.e. value class constructor val)
+ val vals = sym.info.fields.filterNot(_.symbol.is(Flags.ParamAccessor | Flags.Private | Flags.Synthetic)).map { value =>
+ val kind = if (value.symbol.is(Flags.Mutable)) "var" else "val"
ValImpl(
value.symbol,
+ annotations(value.symbol),
value.symbol.name.show,
Nil, path(value.symbol),
returnType(value.info),
+ kind,
implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
)
}
@@ -80,70 +85,140 @@ class DocASTPhase extends Phase {
tree match {
/** package */
case pd @ PackageDef(pid, st) =>
- val newPath = prev :+ pid.name.toString
- addEntity(PackageImpl(pd.symbol, newPath.mkString("."), collectEntityMembers(st, newPath), newPath))
+ addPackage(PackageImpl(pd.symbol, annotations(pd.symbol), pd.symbol.showFullName, collectEntityMembers(st), path(pd.symbol)))
+
+ /** type alias */
+ case t: TypeDef if !t.isClassDef =>
+ val sym = t.symbol
+ if (sym.is(Flags.Synthetic | Flags.Param))
+ NonEntity
+ else
+ TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe))
/** trait */
case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) =>
- val name = n.decode.toString
- val newPath = prev :+ name
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
- TraitImpl(t.symbol, name, collectMembers(rhs), flags(t), newPath, typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))
+ TraitImpl(t.symbol, annotations(t.symbol), n.show, collectMembers(rhs), flags(t), path(t.symbol), typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))
/** objects, on the format "Object$" so drop the last letter */
case o @ TypeDef(n, rhs) if o.symbol.is(Flags.Module) =>
- val name = n.decode.toString.dropRight(1)
+ val name = o.name.show
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
- ObjectImpl(o.symbol, name, collectMembers(rhs, prev :+ name), flags(o), prev :+ (name + "$"), superTypes(o))
+ ObjectImpl(o.symbol, annotations(o.symbol), name.dropRight(1), collectMembers(rhs), flags(o), path(o.symbol).init :+ name, superTypes(o))
/** class / case class */
case c @ TypeDef(n, rhs) if c.symbol.isClass =>
- val name = n.decode.toString
- val newPath = prev :+ name
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
- (c.symbol, name, collectMembers(rhs), flags(c), newPath, typeParams(c.symbol), constructors(c.symbol), superTypes(c), None) match {
+ (c.symbol, annotations(c.symbol), n.show, collectMembers(rhs), flags(c), path(c.symbol), typeParams(c.symbol), constructors(c.symbol), superTypes(c), None, Nil, NonEntity) match {
case x if c.symbol.is(Flags.CaseClass) => CaseClassImpl.tupled(x)
case x => ClassImpl.tupled(x)
}
/** def */
case d: DefDef =>
- DefImpl(d.symbol, d.name.decode.toString, flags(d), path(d.symbol), returnType(d.tpt.tpe), typeParams(d.symbol), paramLists(d.symbol.info))
+ DefImpl(d.symbol, annotations(d.symbol), d.name.decode.toString, flags(d), path(d.symbol), returnType(d.tpt.tpe), typeParams(d.symbol), paramLists(d.symbol.info))
/** val */
case v: ValDef if !v.symbol.is(Flags.ModuleVal) =>
- ValImpl(v.symbol, v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe))
+ val kind = if (v.symbol.is(Flags.Mutable)) "var" else "val"
+ ValImpl(v.symbol, annotations(v.symbol), v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe), kind)
case x => {
- //dottydoc.println(s"Found unwanted entity: $x (${x.pos},\n${x.show}")
+ ctx.docbase.debug(s"Found unwanted entity: $x (${x.pos},\n${x.show}")
NonEntity
}
}
}
- var packages: Map[String, Package] = Map.empty
+ var packages: Map[String, PackageImpl] = Map.empty
+
+ def addPackage(newPkg: PackageImpl): Package = {
+ def mergeMembers(newPkg: PackageImpl, oldPkg: PackageImpl): Unit = {
+ val othersNew = newPkg.members.filterNot(_.kind == "package")
+ val (oldPacks, othersOld) = oldPkg.members.partition(_.kind == "package")
+
+ val others = othersNew ::: othersOld
+ // here we can just choose the old packs, since we're recursively (bottom up)
+ // discovering the tree, we should have met the child packages first, as
+ // such - they were already inserted into the tree
+ val newMembers = (others ++ oldPacks)
- def addEntity(p: Package): Package = {
- def mergedChildren(x1s: List[Entity], x2s: List[Entity]): List[Entity] = {
- val (packs1, others1) = x1s.partition(_.kind == "package")
- val (packs2, others2) = x2s.partition(_.kind == "package")
+ oldPkg.members = newMembers
+ }
+
+ // This function mutates packages in place as not to create any orphaned references
+ def mergedPackages(old: PackageImpl, newPkg: PackageImpl): PackageImpl = {
+ if (old.symbol eq NoSymbol) old.symbol = newPkg.symbol
+ if (old.annotations.isEmpty) old.annotations = newPkg.annotations
+ mergeMembers(newPkg, old)
+ if (old.superTypes.isEmpty) old.superTypes = newPkg.superTypes
+ if (!old.comment.isDefined) old.comment = newPkg.comment
+ old
+ }
- val others = others1 ::: others2
- val packs = (packs1 ::: packs2).groupBy(_.path).map(_._2.head)
+ def insertOrModifyRoot(): PackageImpl = {
+ val modifiedPkg =
+ packages
+ .get(newPkg.name)
+ .map(mergedPackages(_, newPkg))
+ .getOrElse(newPkg)
- (others ++ packs).sortBy(_.name)
+ packages = packages + (modifiedPkg.name -> modifiedPkg)
+ modifiedPkg
}
- val path = p.path.mkString(".")
- val newPack = packages.get(path).map {
- case ex: PackageImpl =>
- if (!ex.comment.isDefined) ex.comment = p.comment
- ex.members = mergedChildren(ex.members, p.members)
- ex
- }.getOrElse(p)
+ // This function inserts a package by creating empty packages to the point
+ // where it can insert the supplied package `newPkg`.
+ def createAndInsert(currentPkg: PackageImpl, path: List[String]): PackageImpl = {
+ (path: @unchecked) match {
+ case x :: Nil => {
+ val existingPkg = currentPkg.members.collect {
+ case p: PackageImpl if p.name == newPkg.name => p
+ }.headOption
+
+ if (existingPkg.isDefined) mergedPackages(existingPkg.get, newPkg)
+ else {
+ currentPkg.members = newPkg :: currentPkg.members
+ newPkg
+ }
+ }
+ case x :: xs => {
+ val subPkg = s"${currentPkg.name}.$x"
+ val existingPkg = currentPkg.members.collect {
+ case p: PackageImpl if p.name == subPkg => p
+ }.headOption
+
+ if (existingPkg.isDefined) createAndInsert(existingPkg.get, xs)
+ else {
+ val newEmpty = EmptyPackage(currentPkg.path :+ x, subPkg)
+ packages = packages + (subPkg -> newEmpty)
+ currentPkg.members = newEmpty :: currentPkg.members
+ createAndInsert(newEmpty, xs)
+ }
+ }
+ }
+ }
- packages = packages + (path -> newPack)
- newPack
+ val path = newPkg.path
+ if (path.length == 1)
+ insertOrModifyRoot()
+ else if (packages.contains(newPkg.name))
+ mergedPackages(packages(newPkg.name), newPkg)
+ else {
+ val root = packages.get(path.head)
+ if (root.isDefined)
+ // Root ancestor of `newPkg` exists, start recursing to point of
+ // insertion. Point of insertion will be the parent package of `newPkg`.
+ //
+ // Which is the first element of `newPkg`'s path - thus we use the tail
+ // to continue traversing down the tree.
+ createAndInsert(root.get, path.tail)
+ else {
+ val newEmpty = EmptyPackage(List(path.head), path.head)
+ packages = packages + (path.head -> newEmpty)
+ createAndInsert(newEmpty, path.tail)
+ }
+ }
}
private[this] var totalRuns = 0
@@ -151,7 +226,7 @@ class DocASTPhase extends Phase {
override def run(implicit ctx: Context): Unit = {
currentRun += 1
- println(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}")
+ ctx.docbase.echo(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}")
collect(ctx.compilationUnit.tpdTree) // Will put packages in `packages` var
}
@@ -162,8 +237,9 @@ class DocASTPhase extends Phase {
// (2) Set parents of entities, needed for linking
for {
- parent <- packages.values
- child <- parent.children
+ parentName <- rootPackages(packages)
+ parent = packages(parentName)
+ child <- parent.members
} setParent(child, to = parent)
// (3) Update Doc AST in ctx.base
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
index cff614528..3de8f68f7 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
@@ -3,18 +3,37 @@ package dottydoc
package core
import dotc.core.Contexts.Context
+import dotc.core.Symbols.Symbol
+import dotc.core.Comments.{ Comment => CompilerComment }
import transform.DocMiniPhase
import model._
import model.internal._
import model.comment._
-import BodyParsers._
+import HtmlParsers._
import util.syntax._
+/** Phase to add docstrings to the Dottydoc AST */
class DocstringPhase extends DocMiniPhase with CommentParser with CommentCleaner {
- private def parsedComment[E <: Entity](ent: E)(implicit ctx: Context): Option[Comment] =
- ctx.docbase.docstring(ent.symbol).map { cmt =>
- parse(ent, ctx.docbase.packages, clean(cmt.raw), cmt.raw, cmt.pos)
- .toComment(_.toHtml(ent))
+ private def getComment(sym: Symbol)(implicit ctx: Context): Option[CompilerComment] =
+ ctx.docbase.docstring(sym)
+ .orElse {
+ // If the symbol doesn't have a docstring, look for an overridden
+ // ancestor with a docstring
+ sym.allOverriddenSymbols.collectFirst {
+ case parentSym if ctx.docbase.docstring(parentSym).isDefined =>
+ parentSym
+ }
+ .flatMap(ctx.docbase.docstring)
+ }
+
+ private def parsedComment(ent: Entity)(implicit ctx: Context): Option[Comment] =
+ getComment(ent.symbol).map { cmt =>
+ val parsed = parse(ent, ctx.docbase.packages, clean(cmt.raw), cmt.raw, cmt.pos)
+
+ if (ctx.settings.wikiSyntax.value)
+ WikiComment(ent, parsed, cmt.pos).comment
+ else
+ MarkdownComment(ent, parsed, cmt.pos).comment
}
override def transformPackage(implicit ctx: Context) = { case ent: PackageImpl =>
@@ -44,4 +63,8 @@ class DocstringPhase extends DocMiniPhase with CommentParser with CommentCleaner
override def transformVal(implicit ctx: Context) = { case ent: ValImpl =>
ent.copy(comment = parsedComment(ent))
}
+
+ override def transformTypeAlias(implicit ctx: Context) = { case ent: TypeAliasImpl =>
+ ent.copy(comment = parsedComment(ent))
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/LinkCompanionsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/LinkCompanionsPhase.scala
new file mode 100644
index 000000000..82bd90da0
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/core/LinkCompanionsPhase.scala
@@ -0,0 +1,46 @@
+package dotty.tools
+package dottydoc
+package core
+
+import dotc.core.Contexts.Context
+import dotc.ast.tpd
+
+import transform.DocMiniPhase
+import model.internal._
+import model._
+import model.factories._
+import dotty.tools.dotc.core.Symbols.Symbol
+import util.syntax._
+
+class LinkCompanions extends DocMiniPhase {
+ private def linkCompanions(ent: Entity)(implicit ctx: Context): ent.type = {
+ ent.children.groupBy(_.name).foreach {
+ case (_, List(x1: Companion, x2: Companion)) => {
+ x1.companionPath = x2.path
+ x2.companionPath = x1.path
+ }
+ case _ => ()
+ }
+ ent
+ }
+
+ override def transformPackage(implicit ctx: Context) = { case ent: PackageImpl =>
+ linkCompanions(ent)
+ }
+
+ override def transformClass(implicit ctx: Context) = { case ent: ClassImpl =>
+ linkCompanions(ent)
+ }
+
+ override def transformCaseClass(implicit ctx: Context) = { case ent: CaseClassImpl =>
+ linkCompanions(ent)
+ }
+
+ override def transformObject(implicit ctx: Context) = { case ent: ObjectImpl =>
+ linkCompanions(ent)
+ }
+
+ override def transformTrait(implicit ctx: Context) = { case ent: TraitImpl =>
+ linkCompanions(ent)
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala b/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala
index 150a4e08f..1f30e089d 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala
@@ -9,6 +9,7 @@ import dotc.core.Phases.Phase
import model._
import model.internal._
import util.syntax._
+import util.traversing._
object transform {
/**
@@ -21,11 +22,11 @@ object transform {
*
* Create a `DocMiniPhase` which overrides the relevant method:
*
- * {{{
- * override def transformDef(implicit ctx: Context) = {
- * case x if shouldTransform(x) => x.copy(newValue = ...)
- * }
- * }}}
+ * ```
+ * override def transformDef(implicit ctx: Context) = {
+ * case x if shouldTransform(x) => x.copy(newValue = ...)
+ * }
+ * ```
*
* On each node in the AST, the appropriate method in `DocMiniPhase` will be
* called in the order that they are supplied in
@@ -39,51 +40,43 @@ object transform {
* `transformPackage`, because `transformX` will be called for the relevant
* children. If you want to add children to `Package` you need to do that in
* `transformPackage`, these additions will be persisted.
+ *
+ * Deleting nodes in the AST
+ * -------------------------
+ * To delete a node in the AST, simply return `NonEntity` from transforming method
*/
abstract class DocMiniTransformations(transformations: List[DocMiniPhase]) extends Phase {
override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
for {
- rootName <- rootPackages
+ rootName <- rootPackages(ctx.docbase.packages)
pack = ctx.docbase.packages(rootName)
transformed = performPackageTransform(pack)
} yield ctx.docbase.packagesMutable(rootName) = transformed
super.runOn(units)
}
- private def rootPackages(implicit ctx: Context): List[String] = {
- var currentDepth = Int.MaxValue
- var packs = List.empty[String]
-
- for (key <- ctx.docbase.packages.keys) {
- val keyDepth = key.split("\\.").length
- packs =
- if (keyDepth < currentDepth) {
- currentDepth = keyDepth
- key :: Nil
- } else if (keyDepth == currentDepth) {
- key :: packs
- } else packs
- }
- packs
- }
-
private def performPackageTransform(pack: Package)(implicit ctx: Context): Package = {
- def transformEntity[E <: Entity](e: E, f: DocMiniPhase => E => E)(createNew: E => E): E = {
+ def transformEntity[E <: Entity](e: E, f: DocMiniPhase => E => E)(createNew: E => E): Entity = {
val transformedEntity = transformations.foldLeft(e) { case (oldE, transf) =>
f(transf)(oldE)
}
- createNew(transformedEntity)
+
+ if (transformedEntity eq NonEntity) NonEntity
+ else createNew(transformedEntity)
}
def traverse(ent: Entity): Entity = ent match {
case p: Package => transformEntity(p, _.packageTransformation) { p =>
val newPackage = PackageImpl(
p.symbol,
+ p.annotations,
p.name,
- p.members.map(traverse),
+ p.members.map(traverse).filterNot(_ eq NonEntity),
p.path,
- p.comment
+ p.superTypes,
+ p.comment,
+ p.parent
)
// Update reference in context to newPackage
@@ -91,59 +84,84 @@ object transform {
newPackage
}
+ case t: TypeAlias => transformEntity(t, _.typeAliasTransformation) { t =>
+ TypeAliasImpl(
+ t.symbol,
+ t.annotations,
+ t.modifiers,
+ t.name,
+ t.path,
+ t.alias,
+ t.comment,
+ t.parent
+ )
+ }
case c: Class => transformEntity(c, _.classTransformation) { cls =>
ClassImpl(
cls.symbol,
+ cls.annotations,
cls.name,
- cls.members.map(traverse),
+ cls.members.map(traverse).filterNot(_ eq NonEntity),
cls.modifiers,
cls.path,
cls.typeParams,
cls.constructors,
cls.superTypes,
- cls.comment
+ cls.comment,
+ cls.companionPath,
+ cls.parent
)
}
case cc: CaseClass => transformEntity(cc, _.caseClassTransformation) { cc =>
CaseClassImpl(
cc.symbol,
+ cc.annotations,
cc.name,
- cc.members.map(traverse),
+ cc.members.map(traverse).filterNot(_ eq NonEntity),
cc.modifiers,
cc.path,
cc.typeParams,
cc.constructors,
cc.superTypes,
- cc.comment
+ cc.comment,
+ cc.companionPath,
+ cc.parent
)
}
case trt: Trait => transformEntity(trt, _.traitTransformation) { trt =>
TraitImpl(
trt.symbol,
+ trt.annotations,
trt.name,
- trt.members.map(traverse),
+ trt.members.map(traverse).filterNot(_ eq NonEntity),
trt.modifiers,
trt.path,
trt.typeParams,
trt.traitParams,
trt.superTypes,
- trt.comment
+ trt.comment,
+ trt.companionPath,
+ trt.parent
)
}
case obj: Object => transformEntity(obj, _.objectTransformation) { obj =>
ObjectImpl(
obj.symbol,
+ obj.annotations,
obj.name,
- obj.members.map(traverse),
+ obj.members.map(traverse).filterNot(_ eq NonEntity),
obj.modifiers,
obj.path,
obj.superTypes,
- obj.comment
+ obj.comment,
+ obj.companionPath,
+ obj.parent
)
}
case df: Def => transformEntity(df, _.defTransformation) { df =>
DefImpl(
df.symbol,
+ df.annotations,
df.name,
df.modifiers,
df.path,
@@ -151,18 +169,22 @@ object transform {
df.typeParams,
df.paramLists,
df.comment,
- df.implicitlyAddedFrom
+ df.implicitlyAddedFrom,
+ df.parent
)
}
case vl: Val => transformEntity(vl, _.valTransformation) { vl =>
ValImpl(
vl.symbol,
+ vl.annotations,
vl.name,
vl.modifiers,
vl.path,
vl.returnValue,
+ vl.kind,
vl.comment,
- vl.implicitlyAddedFrom
+ vl.implicitlyAddedFrom,
+ vl.parent
)
}
}
@@ -185,11 +207,11 @@ object transform {
trait DocMiniPhase { phase =>
private def identity[E]: PartialFunction[E, E] = {
- case id => id
+ case id: E @unchecked => id
}
- // Partial functions instead????
def transformPackage(implicit ctx: Context): PartialFunction[Package, Package] = identity
+ def transformTypeAlias(implicit ctx: Context): PartialFunction[TypeAlias, TypeAlias] = identity
def transformClass(implicit ctx: Context): PartialFunction[Class, Class] = identity
def transformCaseClass(implicit ctx: Context): PartialFunction[CaseClass, CaseClass] = identity
def transformTrait(implicit ctx: Context): PartialFunction[Trait, Trait] = identity
@@ -198,6 +220,7 @@ object transform {
def transformVal(implicit ctx: Context): PartialFunction[Val, Val] = identity
private[transform] def packageTransformation(p: Package)(implicit ctx: Context) = (transformPackage orElse identity)(p)
+ private[transform] def typeAliasTransformation(alias: TypeAlias)(implicit ctx: Context) = (transformTypeAlias orElse identity)(alias)
private[transform] def classTransformation(cls: Class)(implicit ctx: Context) = (transformClass orElse identity)(cls)
private[transform] def caseClassTransformation(cc: CaseClass)(implicit ctx: Context) = (transformCaseClass orElse identity)(cc)
private[transform] def traitTransformation(trt: Trait)(implicit ctx: Context) = (transformTrait orElse identity)(trt)
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/PackageObjectsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/PackageObjectsPhase.scala
new file mode 100644
index 000000000..adcadb0ba
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/core/PackageObjectsPhase.scala
@@ -0,0 +1,35 @@
+package dotty.tools
+package dottydoc
+package core
+
+import dotty.tools.dotc.core.Symbols.Symbol
+import dotc.core.Contexts.Context
+import dotc.ast.tpd
+
+import model._
+import model.internal._
+import util.syntax._
+import transform.DocMiniPhase
+
+class PackageObjectsPhase extends DocMiniPhase {
+
+ override def transformPackage(implicit ctx: Context) = { case pkg: PackageImpl =>
+ pkg
+ .members
+ .collect { case o: Object if o.symbol.isPackageObject => o }
+ .headOption
+ .map { obj =>
+ pkg.copy(
+ members = obj.members ++ pkg.members,
+ superTypes = obj.superTypes,
+ comment = obj.comment
+ )
+ }
+ .getOrElse(pkg)
+ }
+
+ override def transformObject(implicit ctx: Context) = { case obj: Object =>
+ if (obj.symbol.isPackageObject) NonEntity
+ else obj
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/SortMembersPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/SortMembersPhase.scala
index c8de532bb..a281558d4 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/SortMembersPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/SortMembersPhase.scala
@@ -10,23 +10,46 @@ import model.internal._
/** This DocMiniPhase sorts the members of all classes, traits, objects and packages */
class SortMembers extends DocMiniPhase {
+ private implicit val EntityOrdering: Ordering[Entity] = new Ordering[Entity] {
+ def compare(x: Entity, y: Entity): Int = {
+ val nameComp = x.name.compareTo(y.name)
+ if (nameComp == 0) x.kind.compareTo(y.kind)
+ else nameComp
+ }
+ }
+
+ private def sort(xs: List[Entity]): List[Entity] = {
+ def sortOrNil(xs: Option[List[Entity]]*) =
+ xs.map(_.getOrElse(Nil)).reduceLeft(_ ++ _).sorted
+
+ val map = xs.groupBy(_.kind)
+
+ val pkgs = sortOrNil(map.get("package"))
+ val typs = sortOrNil(map.get("type"))
+ val vals = sortOrNil(map.get("val"), map.get("var"))
+ val nested = sortOrNil(map.get("object"), map.get("class"), map.get("case class"), map.get("trait"))
+ val defs = sortOrNil(map.get("def"))
+
+ pkgs ++ nested ++ typs ++ vals ++ defs
+ }
+
override def transformPackage(implicit ctx: Context) = { case p: PackageImpl =>
- p.copy(members = p.members.sortBy(_.name))
+ p.copy(members = sort(p.members))
}
override def transformClass(implicit ctx: Context) = { case c: ClassImpl =>
- c.copy(members = c.members.sortBy(_.name))
+ c.copy(members = sort(c.members))
}
override def transformCaseClass(implicit ctx: Context) = { case cc: CaseClassImpl =>
- cc.copy(members = cc.members.sortBy(_.name))
+ cc.copy(members = sort(cc.members))
}
override def transformTrait(implicit ctx: Context) = { case t: TraitImpl =>
- t.copy(members = t.members.sortBy(_.name))
+ t.copy(members = sort(t.members))
}
override def transformObject(implicit ctx: Context) = { case o: ObjectImpl =>
- o.copy(members = o.members.sortBy(_.name))
+ o.copy(members = sort(o.members))
}
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala b/doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala
index 1aecca9e1..5e0099f4b 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala
@@ -10,7 +10,7 @@ import model._
import model.internal._
import model.comment._
import model.references._
-import BodyParsers._
+import HtmlParsers._
import util.MemberLookup
import util.traversing._
import util.internal.setters._
@@ -26,6 +26,14 @@ class LinkReturnTypes extends DocMiniPhase with TypeLinker {
val returnValue = linkReference(vl, vl.returnValue, ctx.docbase.packages)
vl.copy(returnValue = returnValue)
}
+
+ override def transformTypeAlias(implicit ctx: Context) = { case ta: TypeAliasImpl =>
+ ta.alias.map { alias =>
+ val linkedAlias = linkReference(ta, alias, ctx.docbase.packages)
+ ta.copy(alias = Some(linkedAlias))
+ }
+ .getOrElse(ta)
+ }
}
class LinkParamListTypes extends DocMiniPhase with TypeLinker {
@@ -43,9 +51,7 @@ class LinkSuperTypes extends DocMiniPhase with TypeLinker {
def linkSuperTypes(ent: Entity with SuperTypes)(implicit ctx: Context): List[MaterializableLink] =
ent.superTypes.collect {
case UnsetLink(title, query) =>
- val packages = ctx.docbase.packages
- val entityLink = makeEntityLink(ent, packages, Text(title), NoPosition, query).link
- handleEntityLink(title, entityLink, ent)
+ handleEntityLink(title, lookup(ent, ctx.docbase.packages, query), ent)
}
override def transformClass(implicit ctx: Context) = { case cls: ClassImpl =>
@@ -80,11 +86,11 @@ class LinkImplicitlyAddedTypes extends DocMiniPhase with TypeLinker {
}
trait TypeLinker extends MemberLookup {
- def handleEntityLink(title: String, lt: LinkTo, ent: Entity): MaterializableLink = lt match {
- case Tooltip(str) => NoLink(title, str)
- case LinkToExternal(_, url) => MaterializedLink(title, url)
- case LinkToEntity(target) => MaterializedLink(title, util.traversing.relativePath(ent, target))
- }
+ def handleEntityLink(title: String, target: Option[Entity], ent: Entity, query: String = ""): MaterializableLink =
+ target match {
+ case Some(target) => new MaterializedLink(title, target)
+ case none => NoLink(title, query)
+ }
def linkReference(ent: Entity, ref: Reference, packs: Map[String, Package]): Reference = {
def linkRef(ref: Reference) = linkReference(ent, ref, packs)
@@ -94,7 +100,7 @@ trait TypeLinker extends MemberLookup {
val inlineToHtml = InlineToHtml(ent)
val title = t
- val target = handleEntityLink(title, makeEntityLink(ent, packs, Text(t), NoPosition, query).link, ent)
+ val target = handleEntityLink(title, lookup(ent, packs, query), ent, query)
val tpTargets = tps.map(linkReference(ent, _, packs))
ref.copy(tpeLink = target, paramLinks = tpTargets)
case ref @ OrTypeReference(left, right) =>
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/UsecasePhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/UsecasePhase.scala
index 47376eb26..5940df0bc 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/UsecasePhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/UsecasePhase.scala
@@ -16,6 +16,7 @@ class UsecasePhase extends DocMiniPhase {
val name = d.name.show.split("\\$").head // UseCase defs get $pos appended to their names
DefImpl(
sym,
+ annotations(sym),
name,
flags(d),
path(d.symbol).init :+ name,
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
new file mode 100644
index 000000000..e7cf54a03
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
@@ -0,0 +1,314 @@
+package dotty.tools.dottydoc
+package model
+
+import comment._
+import references._
+
+import _root_.java.util.HashMap
+import _root_.java.util.LinkedList
+
+object JavaConverters {
+ import scala.collection.JavaConverters._
+ import _root_.java.util.{ Optional => JOptional, Map => JMap }
+
+ implicit class OptStr(val opt: Option[String]) extends AnyVal {
+ def asJava = opt.getOrElse(null)
+ }
+
+ implicit class OptMap(val opt: Option[JMap[String, _]]) extends AnyVal {
+ def asJava = opt.getOrElse(Map.empty.asJava)
+ }
+
+ implicit class JavaComment(val cmt: Comment) extends AnyVal {
+ def asJava: JMap[String, _] = Map(
+ "body" -> cmt.body,
+ "short" -> cmt.short,
+ "authors" -> cmt.authors.asJava,
+ "see" -> cmt.see.asJava,
+ "result" -> cmt.result.asJava,
+ "throws" -> cmt.throws.asJava,
+ "valueParams" -> cmt.valueParams.asJava,
+ "typeParams" -> cmt.typeParams.asJava,
+ "version" -> cmt.version.asJava,
+ "since" -> cmt.since.asJava,
+ "todo" -> cmt.todo.asJava,
+ "deprecated" -> cmt.deprecated.asJava,
+ "note" -> cmt.note.asJava,
+ "example" -> cmt.example.asJava,
+ "constructor" -> cmt.constructor.asJava,
+ "group" -> cmt.group.asJava,
+ "groupDesc" -> cmt.groupDesc.asJava,
+ "groupNames" -> cmt.groupNames.asJava,
+ "groupPrio" -> cmt.groupPrio.asJava,
+ "hideImplicitConversions" -> cmt.hideImplicitConversions.asJava
+ ).asJava
+ }
+
+ implicit class JavaPackage(val ent: Package) extends AnyVal {
+ def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "path" -> ent.path.asJava,
+ "members" -> ent.members.map(_.asJava()).asJava,
+ "children" -> ent.children.map(_.asJava()).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "superTypes" -> ent.superTypes,
+ "hasVisibleMembers" -> ent.hasVisibleMembers,
+ "signature" -> ent.signature
+ ) ++ extras).asJava
+ }
+
+ implicit class JavaCaseClass(val ent: CaseClass) extends AnyVal {
+ def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "members" -> ent.members.map(_.asJava()).asJava,
+ "modifiers" -> ent.modifiers.asJava,
+ "path" -> ent.path.asJava,
+ "typeParams" -> ent.typeParams.asJava,
+ "superTypes" -> ent.superTypes.map(_.asJava).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "constructors" -> ent.constructors.map(_.map(_.asJava).asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasCompanion" -> ent.hasCompanion,
+ "companionPath" -> ent.companionPath.asJava,
+ "signature" -> ent.signature
+ ) ++ extras).asJava
+ }
+
+ implicit class JavaClass(val ent: Class) extends AnyVal {
+ def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "members" -> ent.members.map(_.asJava()).asJava,
+ "modifiers" -> ent.modifiers.asJava,
+ "path" -> ent.path.asJava,
+ "typeParams" -> ent.typeParams.asJava,
+ "superTypes" -> ent.superTypes.map(_.asJava).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "constructors" -> ent.constructors.map(_.map(_.asJava).asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasCompanion" -> ent.hasCompanion,
+ "companionPath" -> ent.companionPath.asJava,
+ "signature" -> ent.signature
+ ) ++ extras).asJava
+ }
+
+ implicit class JavaTrait(val ent: Trait) extends AnyVal {
+ def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "members" -> ent.members.map(_.asJava()).asJava,
+ "modifiers" -> ent.modifiers.asJava,
+ "path" -> ent.path.asJava,
+ "typeParams" -> ent.typeParams.asJava,
+ "superTypes" -> ent.superTypes.map(_.asJava).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasCompanion" -> ent.hasCompanion,
+ "companionPath" -> ent.companionPath.asJava,
+ "signature" -> ent.signature
+ ) ++ extras).asJava
+ }
+
+ implicit class JavaObject(val ent: Object) extends AnyVal {
+ def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "members" -> ent.members.map(_.asJava()).asJava,
+ "modifiers" -> ent.modifiers.asJava,
+ "path" -> ent.path.asJava,
+ "superTypes" -> ent.superTypes.map(_.asJava).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasCompanion" -> ent.hasCompanion,
+ "companionPath" -> ent.companionPath.asJava,
+ "signature" -> ent.signature
+ ) ++ extras).asJava
+ }
+
+ implicit class JavaDef(val ent: Def) extends AnyVal {
+ def asJava: JMap[String, _] = Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "modifiers" -> ent.modifiers.asJava,
+ "path" -> ent.path.asJava,
+ "returnValue" -> ent.returnValue.asJava,
+ "typeParams" -> ent.typeParams.asJava,
+ "paramLists" -> ent.paramLists.map(_.asJava).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "signature" -> ent.signature
+ ).asJava
+ }
+
+ implicit class JavaVal(val ent: Val) extends AnyVal {
+ def asJava: JMap[String, _] = Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "name" -> ent.name,
+ "modifiers" -> ent.modifiers.asJava,
+ "path" -> ent.path.asJava,
+ "returnValue" -> ent.returnValue.asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "signature" -> ent.signature
+ ).asJava
+ }
+
+ implicit class JavaTypeAlias(val ent: TypeAlias) extends AnyVal {
+ def asJava: JMap[String, _] = Map(
+ "kind" -> ent.kind,
+ "annotations" -> ent.annotations.asJava,
+ "modifiers" -> ent.modifiers.asJava,
+ "name" -> ent.name,
+ "path" -> ent.path.asJava,
+ "alias" -> ent.alias.map(_.asJava).asJava,
+ "comment" -> ent.comment.map(_.asJava).asJava,
+ "isPrivate" -> ent.isPrivate,
+ "isProtected" -> ent.isProtected,
+ "signature" -> ent.signature
+ ).asJava
+ }
+
+ implicit class JavaParamList(val pl: ParamList) extends AnyVal {
+ def asJava: JMap[String, _] = Map(
+ "list" -> pl.list.map(_.asJava).asJava,
+ "isImplicit" -> pl.isImplicit
+ ).asJava
+ }
+
+ implicit class JavaReference(val ref: Reference) extends AnyVal {
+ def asJava: JMap[String, _] = ref match {
+ case TypeReference(title, tpeLink, paramLinks) => Map(
+ "kind" -> "TypeReference",
+ "title" -> title,
+ "tpeLink" -> tpeLink.asJava,
+ "paramLinks" -> paramLinks.map(_.asJava).asJava,
+ "scala" -> ref
+ ).asJava
+
+ case OrTypeReference(left, right) => Map(
+ "kind" -> "OrTypeReference",
+ "left" -> left.asJava,
+ "right" -> right.asJava,
+ "scala" -> ref
+ ).asJava
+
+ case AndTypeReference(left, right) => Map(
+ "kind" -> "AndTypeReference",
+ "left" -> left.asJava,
+ "right" -> right.asJava,
+ "scala" -> ref
+ ).asJava
+
+ case FunctionReference(args, returnValue) => Map(
+ "kind" -> "FunctionReference",
+ "args" -> args.map(_.asJava).asJava,
+ "returnValue" -> returnValue.asJava,
+ "scala" -> ref
+ ).asJava
+
+ case TupleReference(args) => Map(
+ "kind" -> "TupleReference",
+ "args" -> args.map(_.asJava).asJava,
+ "scala" -> ref
+ ).asJava
+
+ case BoundsReference(low, high) => Map(
+ "kind" -> "BoundsReference",
+ "low" -> low.asJava,
+ "hight" -> high.asJava,
+ "scala" -> ref
+ ).asJava
+
+ case NamedReference(title, ref, isByName, isRepeated) => Map(
+ "kind" -> "NamedReference",
+ "title" -> title,
+ "ref" -> ref.asJava,
+ "isByName" -> isByName,
+ "isRepeated" -> isRepeated,
+ "scala" -> ref
+ ).asJava
+
+ case ConstantReference(title) => Map(
+ "kind" -> "ConstantReference",
+ "title" -> title,
+ "scala" -> ref
+ ).asJava
+
+ case EmptyReference =>
+ throw new IllegalStateException("Empty reference discovered while converting to Java Map")
+ }
+ }
+
+ implicit class JavaMaterializableLink(val link: MaterializableLink) extends AnyVal {
+ def asJava: JMap[String, _] = link match {
+ case UnsetLink(title, query) => Map(
+ "kind" -> "UnsetLink",
+ "title" -> title,
+ "query" -> query,
+ "scala" -> link
+ ).asJava
+
+ case MaterializedLink(title, target) => Map(
+ "kind" -> "MaterializedLink",
+ "title" -> title,
+ "target" -> target,
+ "scala" -> link
+ ).asJava
+
+ case NoLink(title, target) => Map(
+ "kind" -> "NoLink",
+ "title" -> title,
+ "target" -> target,
+ "scala" -> link
+ ).asJava
+ }
+ }
+
+ implicit class JavaEntity(val ent: Entity) extends AnyVal {
+ def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = parseEntity(ent, extras)
+ }
+
+ private def parseEntity(ent: Entity, extras: Map[String, _]): JMap[String, _] = ent match {
+ case ent: Package => ent.asJava(extras)
+ case ent: CaseClass => ent.asJava(extras)
+ case ent: Class => ent.asJava(extras)
+ case ent: Trait => ent.asJava(extras)
+ case ent: Object => ent.asJava(extras)
+ case ent: Def => ent.asJava
+ case ent: Val => ent.asJava
+ case ent: TypeAlias => ent.asJava
+ case _ => Map.empty.asJava
+ }
+
+ 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
+ }
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/BodyEntities.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/BodyEntities.scala
index 29fe48de3..1d49a4f4f 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/BodyEntities.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/BodyEntities.scala
@@ -32,8 +32,8 @@ final case class Body(blocks: Seq[Block]) {
}
(blocks flatMap summaryInBlock).toList match {
case Nil => None
- case inline :: Nil => Some(Body(Seq(Paragraph(inline))))
- case inlines => Some(Body(Seq(Paragraph(Chain(inlines)))))
+ case inl :: Nil => Some(Body(Seq(Paragraph(inl))))
+ case inls => Some(Body(Seq(Paragraph(Chain(inls)))))
}
}
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala
index c4f6ccf5d..5b6c34de8 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/Comment.scala
@@ -3,6 +3,16 @@ package dottydoc
package model
package comment
+import dotty.tools.dottydoc.util.syntax._
+import dotty.tools.dotc.core.Contexts.Context
+import dotty.tools.dotc.util.Positions._
+import dotty.tools.dotc.config.Printers.dottydoc
+import com.vladsch.flexmark.ast.{ Node => MarkdownNode }
+import HtmlParsers._
+import util.MemberLookup
+
+import dotc.util.SourceFile
+
case class Comment (
body: String,
short: String,
@@ -26,3 +36,141 @@ case class Comment (
/** List of conversions to hide - containing e.g: `scala.Predef.FloatArrayOps` */
hideImplicitConversions: List[String]
)
+
+private[comment] case class ParsedComment (
+ body: String,
+ authors: List[String],
+ see: List[String],
+ result: List[String],
+ throws: Map[String, String],
+ valueParams: Map[String, String],
+ typeParams: Map[String, String],
+ version: List[String],
+ since: List[String],
+ todo: List[String],
+ deprecated: List[String],
+ note: List[String],
+ example: List[String],
+ constructor: List[String],
+ group: List[String],
+ groupDesc: Map[String, String],
+ groupNames: Map[String, String],
+ groupPrio: Map[String, String],
+ hideImplicitConversions: List[String],
+ shortDescription: List[String]
+)
+
+trait MarkupConversion[T] extends MemberLookup {
+ def ent: Entity
+ def pos: Position
+ def parsed: ParsedComment
+
+ protected def linkedExceptions(m: Map[String, String])(implicit ctx: Context): Map[String, String]
+ protected def stringToMarkup(str: String)(implicit ctx: Context): T
+ protected def markupToHtml(t: T)(implicit ctx: Context): String
+ protected def stringToShortHtml(str: String)(implicit ctx: Context): String
+ protected def filterEmpty(xs: List[String])(implicit ctx: Context): List[T]
+ protected def filterEmpty(xs: Map[String, String])(implicit ctx: Context): Map[String, T]
+
+ private def single(annot: String, xs: List[String], filter: Boolean = true)(implicit ctx: Context): Option[T] =
+ (if (filter) filterEmpty(xs) else xs.map(stringToMarkup)) match {
+ case x :: xs =>
+ if (xs.nonEmpty) ctx.docbase.warn(
+ s"Only allowed to have a single annotation for $annot",
+ ent.symbol.sourcePosition(pos)
+ )
+ Some(x)
+ case _ => None
+ }
+
+ final def comment(implicit ctx: Context): Comment = Comment(
+ body = markupToHtml(stringToMarkup(parsed.body)),
+ short = stringToShortHtml(parsed.body),
+ authors = filterEmpty(parsed.authors).map(markupToHtml),
+ see = filterEmpty(parsed.see).map(markupToHtml),
+ result = single("@result", parsed.result).map(markupToHtml),
+ throws = linkedExceptions(parsed.throws),
+ valueParams = filterEmpty(parsed.valueParams).mapValues(markupToHtml),
+ typeParams = filterEmpty(parsed.typeParams).mapValues(markupToHtml),
+ version = single("@version", parsed.version).map(markupToHtml),
+ since = single("@since", parsed.since).map(markupToHtml),
+ todo = filterEmpty(parsed.todo).map(markupToHtml),
+ deprecated = single("@deprecated", parsed.deprecated, filter = false).map(markupToHtml),
+ note = filterEmpty(parsed.note).map(markupToHtml),
+ example = filterEmpty(parsed.example).map(markupToHtml),
+ constructor = single("@constructor", parsed.constructor).map(markupToHtml),
+ group = single("@group", parsed.group).map(markupToHtml),
+ groupDesc = filterEmpty(parsed.groupDesc).mapValues(markupToHtml),
+ groupNames = filterEmpty(parsed.groupNames).mapValues(markupToHtml),
+ groupPrio = filterEmpty(parsed.groupPrio).mapValues(markupToHtml),
+ hideImplicitConversions = filterEmpty(parsed.hideImplicitConversions).map(markupToHtml)
+ )
+}
+
+case class MarkdownComment(ent: Entity, parsed: ParsedComment, pos: Position)
+extends MarkupConversion[MarkdownNode] {
+
+ def stringToMarkup(str: String)(implicit ctx: Context) =
+ str.toMarkdown(ent)
+
+ def stringToShortHtml(str: String)(implicit ctx: Context) =
+ str.toMarkdown(ent).shortenAndShow
+
+ def markupToHtml(md: MarkdownNode)(implicit ctx: Context) =
+ md.show
+
+ def linkedExceptions(m: Map[String, String])(implicit ctx: Context) = {
+ val inlineToHtml = InlineToHtml(ent)
+ m.map { case (targetStr, body) =>
+ val link = makeEntityLink(ent, ctx.docbase.packages, Monospace(Text(targetStr)), targetStr)
+ (targetStr, inlineToHtml(link))
+ }
+ }
+
+ def filterEmpty(xs: List[String])(implicit ctx: Context) =
+ xs.map(_.trim)
+ .filterNot(_.isEmpty)
+ .map(stringToMarkup)
+
+ def filterEmpty(xs: Map[String, String])(implicit ctx: Context) =
+ xs.mapValues(_.trim)
+ .filterNot { case (_, v) => v.isEmpty }
+ .mapValues(stringToMarkup)
+}
+
+case class WikiComment(ent: Entity, parsed: ParsedComment, pos: Position)
+extends MarkupConversion[Body] {
+
+ def filterEmpty(xs: Map[String,String])(implicit ctx: Context) =
+ xs.mapValues(_.toWiki(ent, ctx.docbase.packages, pos))
+ .filterNot { case (_, v) => v.blocks.isEmpty }
+
+ def filterEmpty(xs: List[String])(implicit ctx: Context) =
+ xs.map(_.toWiki(ent, ctx.docbase.packages, pos))
+
+ def markupToHtml(t: Body)(implicit ctx: Context) =
+ t.show(ent)
+
+ def stringToMarkup(str: String)(implicit ctx: Context) =
+ str.toWiki(ent, ctx.docbase.packages, pos)
+
+ def stringToShortHtml(str: String)(implicit ctx: Context) = {
+ val parsed = stringToMarkup(str)
+ parsed.summary.getOrElse(parsed).show(ent)
+ }
+
+ def linkedExceptions(m: Map[String, String])(implicit ctx: Context) = {
+ m.mapValues(_.toWiki(ent, ctx.docbase.packages, pos)).map { case (targetStr, body) =>
+ val link = lookup(ent, ctx.docbase.packages, targetStr)
+ val newBody = body match {
+ case Body(List(Paragraph(Chain(content)))) =>
+ val descr = Text(" ") +: content
+ val link = makeEntityLink(ent, ctx.docbase.packages, Monospace(Text(targetStr)), targetStr)
+ Body(List(Paragraph(Chain(link +: descr))))
+ case _ => body
+ }
+
+ (targetStr, newBody.show(ent))
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentCleaner.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentCleaner.scala
index 27b0ff977..5b60cd5f9 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentCleaner.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentCleaner.scala
@@ -4,6 +4,7 @@ package comment
trait CommentCleaner {
import Regexes._
+ import java.util.regex.Matcher
def clean(comment: String): List[String] = {
def cleanLine(line: String): String = {
@@ -18,8 +19,8 @@ trait CommentCleaner {
val javadoclessComment = JavadocTags.replaceAllIn(safeComment, { javadocReplacement(_) })
val markedTagComment =
SafeTags.replaceAllIn(javadoclessComment, { mtch =>
- _root_.java.util.regex.Matcher.quoteReplacement(safeTagMarker + mtch.matched + safeTagMarker)
+ Matcher.quoteReplacement(safeTagMarker + mtch.matched + safeTagMarker)
})
- markedTagComment.lines.toList map (cleanLine(_))
+ markedTagComment.lines.toList map (cleanLine)
}
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala
index 9685b6934..b7a33a7ef 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala
@@ -2,70 +2,20 @@ package dotty.tools.dottydoc
package model
package comment
+import dotty.tools.dottydoc.util.syntax._
import dotty.tools.dotc.util.Positions._
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.core.Contexts.Context
import scala.collection.mutable
import dotty.tools.dotc.config.Printers.dottydoc
import scala.util.matching.Regex
+import com.vladsch.flexmark.ast.{ Node => MarkdownNode }
+import com.vladsch.flexmark.parser.{ Parser => MarkdownParser }
trait CommentParser extends util.MemberLookup {
import Regexes._
import model.internal._
- case class FullComment (
- body: Body,
- authors: List[Body],
- see: List[Body],
- result: Option[Body],
- throws: Map[String, Body],
- valueParams: Map[String, Body],
- typeParams: Map[String, Body],
- version: Option[Body],
- since: Option[Body],
- todo: List[Body],
- deprecated: Option[Body],
- note: List[Body],
- example: List[Body],
- constructor: Option[Body],
- group: Option[Body],
- groupDesc: Map[String, Body],
- groupNames: Map[String, Body],
- groupPrio: Map[String, Body],
- hideImplicitConversions: List[Body],
- shortDescription: List[Body]
- ) {
-
- /**
- * Transform this CommentParser.FullComment to a Comment using the supplied
- * Body transformer
- */
- def toComment(transform: Body => String) = Comment(
- transform(body),
- short =
- if (shortDescription.nonEmpty) shortDescription.map(transform).mkString
- else body.summary.map(transform).getOrElse(""),
- authors.map(transform),
- see.map(transform),
- result.map(transform),
- throws.map { case (k, v) => (k, transform(v)) },
- valueParams.map { case (k, v) => (k, transform(v)) },
- typeParams.map { case (k, v) => (k, transform(v)) },
- version.map(transform),
- since.map(transform),
- todo.map(transform),
- deprecated.map(transform),
- note.map(transform),
- example.map(transform),
- constructor.map(transform),
- group.map(transform),
- groupDesc.map { case (k, v) => (k, transform(v)) },
- groupNames.map { case (k, v) => (k, transform(v)) },
- groupPrio.map { case (k, v) => (k, transform(v)) },
- hideImplicitConversions.map(transform)
- )
- }
-
/** Parses a raw comment string into a `Comment` object.
* @param packages all packages parsed by Scaladoc tool, used for lookup
* @param cleanComment a cleaned comment to be parsed
@@ -79,29 +29,29 @@ trait CommentParser extends util.MemberLookup {
src: String,
pos: Position,
site: Symbol = NoSymbol
- )(implicit ctx: Context): FullComment = {
+ )(implicit ctx: Context): ParsedComment = {
/** Parses a comment (in the form of a list of lines) to a `Comment`
- * instance, recursively on lines. To do so, it splits the whole comment
- * into main body and tag bodies, then runs the `WikiParser` on each body
- * before creating the comment instance.
- *
- * @param docBody The body of the comment parsed until now.
- * @param tags All tags parsed until now.
- * @param lastTagKey The last parsed tag, or `None` if the tag section
- * hasn't started. Lines that are not tagged are part
- * of the previous tag or, if none exists, of the body.
- * @param remaining The lines that must still recursively be parsed.
- * @param inCodeBlock Whether the next line is part of a code block (in
- * which no tags must be read).
- */
+ * instance, recursively on lines. To do so, it splits the whole comment
+ * into main body and tag bodies, then runs the `WikiParser` on each body
+ * before creating the comment instance.
+ *
+ * @param docBody The body of the comment parsed until now.
+ * @param tags All tags parsed until now.
+ * @param lastTagKey The last parsed tag, or `None` if the tag section
+ * hasn't started. Lines that are not tagged are part
+ * of the previous tag or, if none exists, of the body.
+ * @param remaining The lines that must still recursively be parsed.
+ * @param inCodeBlock Whether the next line is part of a code block (in
+ * which no tags must be read).
+ */
def parseComment (
docBody: StringBuilder,
tags: Map[TagKey, List[String]],
lastTagKey: Option[TagKey],
remaining: List[String],
inCodeBlock: Boolean
- ): FullComment = remaining match {
+ ): ParsedComment = remaining match {
case CodeBlockStartRegex(before, marker, after) :: ls if (!inCodeBlock) =>
if (!before.trim.isEmpty && !after.trim.isEmpty)
@@ -194,24 +144,16 @@ trait CommentParser extends util.MemberLookup {
case None => List.empty
}
- val stripTags=List(inheritDiagramTag, contentDiagramTag, SimpleTagKey("template"), SimpleTagKey("documentable"))
+ val stripTags = List(inheritDiagramTag, contentDiagramTag, SimpleTagKey("template"), SimpleTagKey("documentable"))
val tagsWithoutDiagram = tags.filterNot(pair => stripTags.contains(pair._1))
- val bodyTags: mutable.Map[TagKey, List[Body]] =
- mutable.Map((tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(entity, packages, _, pos, site))}).toSeq: _*)
-
- def oneTag(key: SimpleTagKey, filterEmpty: Boolean = true): Option[Body] =
- ((bodyTags remove key): @unchecked) match {
- case Some(r :: rs) if !(filterEmpty && r.blocks.isEmpty) =>
- if (!rs.isEmpty) dottydoc.println(s"$pos: only one '@${key.name}' tag is allowed")
- Some(r)
- case _ => None
- }
+ val bodyTags: mutable.Map[TagKey, List[String]] =
+ mutable.Map((tagsWithoutDiagram).toSeq: _*)
- def allTags[B](key: SimpleTagKey): List[Body] =
- (bodyTags remove key).getOrElse(Nil).filterNot(_.blocks.isEmpty).reverse
+ def allTags(key: SimpleTagKey): List[String] =
+ (bodyTags remove key).getOrElse(Nil).reverse
- def allSymsOneTag(key: TagKey, filterEmpty: Boolean = true): Map[String, Body] = {
+ def allSymsOneTag(key: TagKey, filterEmpty: Boolean = true): Map[String, String] = {
val keys: Seq[SymbolTagKey] =
bodyTags.keys.toSeq flatMap {
case stk: SymbolTagKey if (stk.name == key.name) => Some(stk)
@@ -220,48 +162,32 @@ trait CommentParser extends util.MemberLookup {
None
case _ => None
}
- val pairs: Seq[(String, Body)] =
+ val pairs: Seq[(String, String)] =
for (key <- keys) yield {
val bs = (bodyTags remove key).get
if (bs.length > 1)
dottydoc.println(s"$pos: only one '@${key.name}' tag for symbol ${key.symbol} is allowed")
(key.symbol, bs.head)
}
- Map.empty[String, Body] ++ (if (filterEmpty) pairs.filterNot(_._2.blocks.isEmpty) else pairs)
+ Map.empty[String, String] ++ pairs
}
- def linkedExceptions: Map[String, Body] = {
- val m = allSymsOneTag(SimpleTagKey("throws"), filterEmpty = false)
-
- m.map { case (targetStr,body) =>
- val link = lookup(entity, packages, targetStr, pos)
- val newBody = body match {
- case Body(List(Paragraph(Chain(content)))) =>
- val descr = Text(" ") +: content
- val entityLink = EntityLink(Monospace(Text(targetStr)), link)
- Body(List(Paragraph(Chain(entityLink +: descr))))
- case _ => body
- }
- (targetStr, newBody)
- }
- }
-
- val cmt = FullComment(
- body = parseWikiAtSymbol(entity, packages, docBody.toString, pos, site),
+ val cmt = ParsedComment(
+ body = docBody.toString,
authors = allTags(SimpleTagKey("author")),
see = allTags(SimpleTagKey("see")),
- result = oneTag(SimpleTagKey("return")),
- throws = linkedExceptions,
+ result = allTags(SimpleTagKey("return")),
+ throws = allSymsOneTag(SimpleTagKey("throws")),
valueParams = allSymsOneTag(SimpleTagKey("param")),
typeParams = allSymsOneTag(SimpleTagKey("tparam")),
- version = oneTag(SimpleTagKey("version")),
- since = oneTag(SimpleTagKey("since")),
+ version = allTags(SimpleTagKey("version")),
+ since = allTags(SimpleTagKey("since")),
todo = allTags(SimpleTagKey("todo")),
- deprecated = oneTag(SimpleTagKey("deprecated"), filterEmpty = false),
+ deprecated = allTags(SimpleTagKey("deprecated")),
note = allTags(SimpleTagKey("note")),
example = allTags(SimpleTagKey("example")),
- constructor = oneTag(SimpleTagKey("constructor")),
- group = oneTag(SimpleTagKey("group")),
+ constructor = allTags(SimpleTagKey("constructor")),
+ group = allTags(SimpleTagKey("group")),
groupDesc = allSymsOneTag(SimpleTagKey("groupdesc")),
groupNames = allSymsOneTag(SimpleTagKey("groupname")),
groupPrio = allSymsOneTag(SimpleTagKey("groupprio")),
@@ -269,8 +195,14 @@ trait CommentParser extends util.MemberLookup {
shortDescription = allTags(SimpleTagKey("shortDescription"))
)
- for ((key, _) <- bodyTags)
- dottydoc.println(s"$pos: Tag '@${key.name}' is not recognised")
+ for ((key, _) <- bodyTags) ctx.docbase.warn(
+ s"Tag '@${key.name}' is not recognised",
+ // FIXME: here the position is stretched out over the entire comment,
+ // with the point being at the very end. This ensures that the entire
+ // comment will be visible in error reporting. A more fine-grained
+ // reporting would be amazing here.
+ entity.symbol.sourcePosition(Position(pos.start, pos.end, pos.end))
+ )
cmt
}
@@ -306,541 +238,4 @@ trait CommentParser extends util.MemberLookup {
pos: Position,
site: Symbol
)(implicit ctx: Context): Body = new WikiParser(entity, packages, string, pos, site).document()
-
- /** Original wikiparser from NSC
- * @author Ingo Maier
- * @author Manohar Jonnalagedda
- * @author Gilles Dubochet
- */
- protected final class WikiParser(
- entity: Entity,
- packages: Map[String, Package],
- val buffer: String,
- pos: Position,
- site: Symbol
- )(implicit ctx: Context) extends CharReader(buffer) { wiki =>
- var summaryParsed = false
-
- def document(): Body = {
- val blocks = new mutable.ListBuffer[Block]
- while (char != endOfText)
- blocks += block()
- Body(blocks.toList)
- }
-
- /* BLOCKS */
-
- /** {{{ block ::= code | title | hrule | listBlock | para }}} */
- def block(): Block = {
- if (checkSkipInitWhitespace("{{{"))
- code()
- else if (checkSkipInitWhitespace('='))
- title()
- else if (checkSkipInitWhitespace("----"))
- hrule()
- else if (checkList)
- listBlock
- else {
- para()
- }
- }
-
- /** listStyle ::= '-' spc | '1.' spc | 'I.' spc | 'i.' spc | 'A.' spc | 'a.' spc
- * Characters used to build lists and their constructors */
- protected val listStyles = Map[String, (Seq[Block] => Block)](
- "- " -> ( UnorderedList(_) ),
- "1. " -> ( OrderedList(_,"decimal") ),
- "I. " -> ( OrderedList(_,"upperRoman") ),
- "i. " -> ( OrderedList(_,"lowerRoman") ),
- "A. " -> ( OrderedList(_,"upperAlpha") ),
- "a. " -> ( OrderedList(_,"lowerAlpha") )
- )
-
- /** Checks if the current line is formed with more than one space and one the listStyles */
- def checkList =
- (countWhitespace > 0) && (listStyles.keys exists { checkSkipInitWhitespace(_) })
-
- /** {{{
- * nListBlock ::= nLine { mListBlock }
- * nLine ::= nSpc listStyle para '\n'
- * }}}
- * Where n and m stand for the number of spaces. When `m > n`, a new list is nested. */
- def listBlock(): Block = {
-
- /** Consumes one list item block and returns it, or None if the block is
- * not a list or a different list. */
- def listLine(indent: Int, style: String): Option[Block] =
- if (countWhitespace > indent && checkList)
- Some(listBlock)
- else if (countWhitespace != indent || !checkSkipInitWhitespace(style))
- None
- else {
- jumpWhitespace()
- jump(style)
- val p = Paragraph(inline(isInlineEnd = false))
- blockEnded("end of list line ")
- Some(p)
- }
-
- /** Consumes all list item blocks (possibly with nested lists) of the
- * same list and returns the list block. */
- def listLevel(indent: Int, style: String): Block = {
- val lines = mutable.ListBuffer.empty[Block]
- var line: Option[Block] = listLine(indent, style)
- while (line.isDefined) {
- lines += line.get
- line = listLine(indent, style)
- }
- val constructor = listStyles(style)
- constructor(lines)
- }
-
- val indent = countWhitespace
- val style = (listStyles.keys find { checkSkipInitWhitespace(_) }).getOrElse(listStyles.keys.head)
- listLevel(indent, style)
- }
-
- def code(): Block = {
- jumpWhitespace()
- jump("{{{")
- val str = readUntil("}}}")
- if (char == endOfText)
- reportError(pos, "unclosed code block")
- else
- jump("}}}")
- blockEnded("code block")
- Code(normalizeIndentation(str))
- }
-
- /** {{{ title ::= ('=' inline '=' | "==" inline "==" | ...) '\n' }}} */
- def title(): Block = {
- jumpWhitespace()
- val inLevel = repeatJump('=')
- val text = inline(check("=" * inLevel))
- val outLevel = repeatJump('=', inLevel)
- if (inLevel != outLevel)
- reportError(pos, "unbalanced or unclosed heading")
- blockEnded("heading")
- Title(text, inLevel)
- }
-
- /** {{{ hrule ::= "----" { '-' } '\n' }}} */
- def hrule(): Block = {
- jumpWhitespace()
- repeatJump('-')
- blockEnded("horizontal rule")
- HorizontalRule()
- }
-
- /** {{{ para ::= inline '\n' }}} */
- def para(): Block = {
- val p =
- if (summaryParsed)
- Paragraph(inline(isInlineEnd = false))
- else {
- val s = summary()
- val r =
- if (checkParaEnded()) List(s) else List(s, inline(isInlineEnd = false))
- summaryParsed = true
- Paragraph(Chain(r))
- }
- while (char == endOfLine && char != endOfText)
- nextChar()
- p
- }
-
- /* INLINES */
-
- val OPEN_TAG = "^<([A-Za-z]+)( [^>]*)?(/?)>$".r
- val CLOSE_TAG = "^</([A-Za-z]+)>$".r
- private def readHTMLFrom(begin: HtmlTag): String = {
- val list = mutable.ListBuffer.empty[String]
- val stack = mutable.ListBuffer.empty[String]
-
- begin.close match {
- case Some(HtmlTag(CLOSE_TAG(s))) =>
- stack += s
- case _ =>
- return ""
- }
-
- do {
- val str = readUntil { char == safeTagMarker || char == endOfText }
- nextChar()
-
- list += str
-
- str match {
- case OPEN_TAG(s, _, standalone) => {
- if (standalone != "/") {
- stack += s
- }
- }
- case CLOSE_TAG(s) => {
- if (s == stack.last) {
- stack.remove(stack.length-1)
- }
- }
- case _ => ;
- }
- } while (stack.length > 0 && char != endOfText)
-
- list mkString ""
- }
-
- def inline(isInlineEnd: => Boolean): Inline = {
-
- def inline0(): Inline = {
- if (char == safeTagMarker) {
- val tag = htmlTag()
- HtmlTag(tag.data + readHTMLFrom(tag))
- }
- else if (check("'''")) bold()
- else if (check("''")) italic()
- else if (check("`")) monospace()
- else if (check("__")) underline()
- else if (check("^")) superscript()
- else if (check(",,")) subscript()
- else if (check("[[")) link()
- else {
- val str = readUntil {
- char == safeTagMarker ||
- check("''") ||
- char == '`' ||
- check("__") ||
- char == '^' ||
- check(",,") ||
- check("[[") ||
- isInlineEnd ||
- checkParaEnded ||
- char == endOfLine
- }
- Text(str)
- }
- }
-
- val inlines: List[Inline] = {
- val iss = mutable.ListBuffer.empty[Inline]
- iss += inline0()
- while (!isInlineEnd && !checkParaEnded) {
- val skipEndOfLine = if (char == endOfLine) {
- nextChar()
- true
- } else {
- false
- }
-
- val current = inline0()
- (iss.last, current) match {
- case (Text(t1), Text(t2)) if skipEndOfLine =>
- iss.update(iss.length - 1, Text(t1 + endOfLine + t2))
- case (i1, i2) if skipEndOfLine =>
- iss ++= List(Text(endOfLine.toString), i2)
- case _ => iss += current
- }
- }
- iss.toList
- }
-
- inlines match {
- case Nil => Text("")
- case i :: Nil => i
- case is => Chain(is)
- }
-
- }
-
- def htmlTag(): HtmlTag = {
- jump(safeTagMarker)
- val read = readUntil(safeTagMarker)
- if (char != endOfText) jump(safeTagMarker)
- HtmlTag(read)
- }
-
- def bold(): Inline = {
- jump("'''")
- val i = inline(check("'''"))
- jump("'''")
- Bold(i)
- }
-
- def italic(): Inline = {
- jump("''")
- val i = inline(check("''"))
- jump("''")
- Italic(i)
- }
-
- def monospace(): Inline = {
- jump("`")
- val i = inline(check("`"))
- jump("`")
- Monospace(i)
- }
-
- def underline(): Inline = {
- jump("__")
- val i = inline(check("__"))
- jump("__")
- Underline(i)
- }
-
- def superscript(): Inline = {
- jump("^")
- val i = inline(check("^"))
- if (jump("^")) {
- Superscript(i)
- } else {
- Chain(Seq(Text("^"), i))
- }
- }
-
- def subscript(): Inline = {
- jump(",,")
- val i = inline(check(",,"))
- jump(",,")
- Subscript(i)
- }
-
- def summary(): Inline = {
- val i = inline(checkSentenceEnded())
- Summary(
- if (jump("."))
- Chain(List(i, Text(".")))
- else
- i
- )
- }
-
- def link(): Inline = {
- val SchemeUri = """([a-z]+:.*)""".r
- jump("[[")
- val parens = 2 + repeatJump('[')
- val stop = "]" * parens
- val target = readUntil { check(stop) || isWhitespaceOrNewLine(char) }
- val title =
- if (!check(stop)) Some({
- jumpWhitespaceOrNewLine()
- inline(check(stop))
- })
- else None
- jump(stop)
-
- (target, title) match {
- case (SchemeUri(uri), optTitle) =>
- Link(uri, optTitle getOrElse Text(uri))
- case (qualName, optTitle) =>
- makeEntityLink(entity, packages, optTitle getOrElse Text(target), pos, target)
- }
- }
-
- /* UTILITY */
-
- /** {{{ eol ::= { whitespace } '\n' }}} */
- def blockEnded(blockType: String): Unit = {
- if (char != endOfLine && char != endOfText) {
- reportError(pos, "no additional content on same line after " + blockType)
- jumpUntil(endOfLine)
- }
- while (char == endOfLine)
- nextChar()
- }
-
- /**
- * Eliminates the (common) leading spaces in all lines, based on the first line
- * For indented pieces of code, it reduces the indent to the least whitespace prefix:
- * {{{
- * indented example
- * another indented line
- * if (condition)
- * then do something;
- * ^ this is the least whitespace prefix
- * }}}
- */
- def normalizeIndentation(_code: String): String = {
-
- val code = _code.replaceAll("\\s+$", "").dropWhile(_ == '\n') // right-trim + remove all leading '\n'
- val lines = code.split("\n")
-
- // maxSkip - size of the longest common whitespace prefix of non-empty lines
- val nonEmptyLines = lines.filter(_.trim.nonEmpty)
- val maxSkip = if (nonEmptyLines.isEmpty) 0 else nonEmptyLines.map(line => line.prefixLength(_ == ' ')).min
-
- // remove common whitespace prefix
- lines.map(line => if (line.trim.nonEmpty) line.substring(maxSkip) else line).mkString("\n")
- }
-
- def checkParaEnded(): Boolean = {
- (char == endOfText) ||
- ((char == endOfLine) && {
- val poff = offset
- nextChar() // read EOL
- val ok = {
- checkSkipInitWhitespace(endOfLine) ||
- checkSkipInitWhitespace('=') ||
- checkSkipInitWhitespace("{{{") ||
- checkList ||
- checkSkipInitWhitespace('\u003D')
- }
- offset = poff
- ok
- })
- }
-
- def checkSentenceEnded(): Boolean = {
- (char == '.') && {
- val poff = offset
- nextChar() // read '.'
- val ok = char == endOfText || char == endOfLine || isWhitespace(char)
- offset = poff
- ok
- }
- }
-
- def reportError(pos: Position, message: String) =
- dottydoc.println(s"$pos: $message")
- }
-
- protected sealed class CharReader(buffer: String) { reader =>
-
- var offset: Int = 0
- def char: Char =
- if (offset >= buffer.length) endOfText else buffer charAt offset
-
- final def nextChar() =
- offset += 1
-
- final def check(chars: String): Boolean = {
- val poff = offset
- val ok = jump(chars)
- offset = poff
- ok
- }
-
- def checkSkipInitWhitespace(c: Char): Boolean = {
- val poff = offset
- jumpWhitespace()
- val ok = jump(c)
- offset = poff
- ok
- }
-
- def checkSkipInitWhitespace(chars: String): Boolean = {
- val poff = offset
- jumpWhitespace()
- val (ok0, chars0) =
- if (chars.charAt(0) == ' ')
- (offset > poff, chars substring 1)
- else
- (true, chars)
- val ok = ok0 && jump(chars0)
- offset = poff
- ok
- }
-
- def countWhitespace: Int = {
- var count = 0
- val poff = offset
- while (isWhitespace(char) && char != endOfText) {
- nextChar()
- count += 1
- }
- offset = poff
- count
- }
-
- /* Jumpers */
-
- /** Jumps a character and consumes it
- * @return true only if the correct character has been jumped */
- final def jump(ch: Char): Boolean = {
- if (char == ch) {
- nextChar()
- true
- }
- else false
- }
-
- /** Jumps all the characters in chars, consuming them in the process.
- * @return true only if the correct characters have been jumped
- */
- final def jump(chars: String): Boolean = {
- var index = 0
- while (index < chars.length && char == chars.charAt(index) && char != endOfText) {
- nextChar()
- index += 1
- }
- index == chars.length
- }
-
- final def repeatJump(c: Char, max: Int = Int.MaxValue): Int = {
- var count = 0
- while (jump(c) && count < max)
- count += 1
- count
- }
-
- final def jumpUntil(ch: Char): Int = {
- var count = 0
- while (char != ch && char != endOfText) {
- nextChar()
- count += 1
- }
- count
- }
-
- final def jumpUntil(pred: => Boolean): Int = {
- var count = 0
- while (!pred && char != endOfText) {
- nextChar()
- count += 1
- }
- count
- }
-
- def jumpWhitespace() = jumpUntil(!isWhitespace(char))
-
- def jumpWhitespaceOrNewLine() = jumpUntil(!isWhitespaceOrNewLine(char))
-
-
- /* Readers */
- final def readUntil(c: Char): String = {
- withRead {
- while (char != c && char != endOfText) {
- nextChar()
- }
- }
- }
-
- final def readUntil(chars: String): String = {
- assert(chars.length > 0)
- withRead {
- val c = chars.charAt(0)
- while (!check(chars) && char != endOfText) {
- nextChar()
- while (char != c && char != endOfText)
- nextChar()
- }
- }
- }
-
- final def readUntil(pred: => Boolean): String = {
- withRead {
- while (char != endOfText && !pred) {
- nextChar()
- }
- }
- }
-
- private def withRead(read: => Unit): String = {
- val start = offset
- read
- buffer.substring(start, offset)
- }
-
- /* Chars classes */
- def isWhitespace(c: Char) = c == ' ' || c == '\t'
-
- def isWhitespaceOrNewLine(c: Char) = isWhitespace(c) || c == '\n'
- }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentRegex.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentRegex.scala
index 2d75b0c66..faefd19a7 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentRegex.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentRegex.scala
@@ -11,7 +11,7 @@ object Regexes {
* one leading whitespace and all trailing whitespace
*/
val CleanCommentLine =
- new Regex("""(?:\s*\*\s?)?(.*)""")
+ new Regex("""(?:\s*\*\s?\s?)?(.*)""")
/** Dangerous HTML tags that should be replaced by something safer,
* such as wiki syntax, or that should be dropped
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/BodyParsers.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala
index 8c1fa8d49..1faa25f32 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/BodyParsers.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/HtmlParsers.scala
@@ -1,11 +1,81 @@
-package dotty.tools.dottydoc
+package dotty.tools
+package dottydoc
package model
package comment
-object BodyParsers {
+import dotc.core.Contexts.Context
+import dotc.util.Positions._
+import dotty.tools.dottydoc.util.syntax._
+import util.MemberLookup
+
+import com.vladsch.flexmark.ast.{ Node => MarkdownNode }
+import com.vladsch.flexmark.html.HtmlRenderer
+import com.vladsch.flexmark.parser.Parser
+import com.vladsch.flexmark.util.sequence.CharSubSequence
+
+object HtmlParsers {
+
+ implicit class StringToMarkdown(val text: String) extends AnyVal {
+ def toMarkdown(origin: Entity)(implicit ctx: Context): MarkdownNode = {
+ import com.vladsch.flexmark.ast.{ Link, Visitor, VisitHandler, NodeVisitor }
+
+ val inlineToHtml = InlineToHtml(origin)
+
+ val node = Parser.builder(staticsite.Site.markdownOptions)
+ .build.parse(text)
+
+ def isOuter(url: String) =
+ url.startsWith("http://") ||
+ url.startsWith("https://") ||
+ url.startsWith("ftp://") ||
+ url.startsWith("ftps://")
+
+ def isRelative(url: String) =
+ url.startsWith("../") ||
+ url.startsWith("./")
+
+ val linkVisitor = new NodeVisitor(
+ new VisitHandler(classOf[Link], new Visitor[Link] with MemberLookup {
+ def queryToUrl(title: String, link: String) = makeEntityLink(origin, ctx.docbase.packages, Text(title), link).link match {
+ case Tooltip(_) => "#"
+ case LinkToExternal(_, url) => url
+ case LinkToEntity(t: Entity) => t match {
+ case e: Entity with Members => inlineToHtml.relativePath(t)
+ case x => x.parent.fold("#") { xpar => inlineToHtml.relativePath(xpar) }
+ }
+ }
+
+ override def visit(link: Link) = {
+ val linkUrl = link.getUrl.toString
+ if (!isOuter(linkUrl) && !isRelative(linkUrl))
+ link.setUrl(CharSubSequence.of(queryToUrl(link.getTitle.toString, linkUrl)))
+ }
+ })
+ )
+
+ linkVisitor.visit(node)
+ node
+ }
+
+ def toMarkdownString(origin: Entity)(implicit ctx: Context): String =
+ toMarkdown(origin).show
+ }
+
+ implicit class MarkdownToHtml(val markdown: MarkdownNode) extends AnyVal {
+ def show(implicit ctx: Context): String =
+ HtmlRenderer.builder(staticsite.Site.markdownOptions).build().render(markdown)
+
+ def shortenAndShow(implicit ctx: Context): String =
+ (new MarkdownShortener).shorten(markdown).show
+ }
+
+ implicit class StringToWiki(val text: String) extends AnyVal {
+ def toWiki(origin: Entity, packages: Map[String, Package], pos: Position): Body =
+ new WikiParser(origin, packages, text, pos, origin.symbol).document()
+ }
implicit class BodyToHtml(val body: Body) extends AnyVal {
- def toHtml(origin: Entity): String = {
+ def show(origin: Entity): String = {
val inlineToHtml = InlineToHtml(origin)
def bodyToHtml(body: Body): String =
@@ -33,8 +103,8 @@ object BodyParsers {
item match {
case OrderedList(_, _) | UnorderedList(_) => // html requires sub ULs to be put into the last LI
list + s"<li>${blockToHtml(item)}</li>"
- case Paragraph(inline) =>
- list + s"<li>${inlineToHtml(inline)}</li>" // LIs are blocks, no need to use Ps
+ case Paragraph(inl) =>
+ list + s"<li>${inlineToHtml(inl)}</li>" // LIs are blocks, no need to use Ps
case block =>
list + s"<li>${blockToHtml(block)}</li>"
}
@@ -45,12 +115,12 @@ object BodyParsers {
}
case class InlineToHtml(origin: Entity) {
- def apply(inline: Inline) = toHtml(inline)
+ def apply(inl: Inline) = toHtml(inl)
def relativePath(target: Entity) =
util.traversing.relativePath(origin, target)
- def toHtml(inline: Inline): String = inline match {
+ def toHtml(inl: Inline): String = inl match {
case Chain(items) => (items map toHtml).mkString
case Italic(in) => s"<i>${toHtml(in)}</i>"
case Bold(in) => s"<b>${toHtml(in)}</b>"
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala
new file mode 100644
index 000000000..311f1e2cb
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/MarkdownShortener.scala
@@ -0,0 +1,83 @@
+package dotty.tools
+package dottydoc
+package model
+package comment
+
+/** The `MarkdownShortener` takes a node and *mutates* it and all children so
+ * that the displayed length of the generated HTML doesn't exceeed `maxLen`.
+ * This number defaults to 150 characters.
+ *
+ * @note calling `shorten` **will** mutate the Markdown AST node.
+ */
+class MarkdownShortener {
+ import com.vladsch.flexmark.ast._
+
+ def shorten(node: Node, maxLen: Int = 150): Node = {
+ var len = 0
+ var didUnlink = false
+
+ def count(node: Node, length: => Int, shortenOrUnlink: Int => Unit) = {
+ val remaining = math.max(maxLen - len, 0)
+ if (didUnlink || remaining == 0) node.unlink()
+ else {
+ if (length <= remaining) len += length
+ else {
+ shortenOrUnlink(remaining)
+ len = maxLen
+ }
+ }
+ }
+
+ val nodeVisitor = new NodeVisitor(
+ new VisitHandler(classOf[Text], new Visitor[Text] {
+ override def visit(node: Text) = count(
+ node,
+ node.getChars.length,
+ remaining => node.setChars(
+ node.getChars.subSequence(0, remaining).trimEnd.append("...")
+ )
+ )
+ }),
+ new VisitHandler(classOf[Code], new Visitor[Code] {
+ override def visit(node: Code) = count(
+ node,
+ node.getText.length,
+ remaining => node.setText(
+ node.getText.subSequence(0, remaining).trimEnd.append("...")
+ )
+ )
+ }),
+ new VisitHandler(classOf[Image], new Visitor[Image] {
+ override def visit(node: Image) = count(node, maxLen, _ => node.unlink())
+ }),
+ new VisitHandler(classOf[FencedCodeBlock], new Visitor[FencedCodeBlock] {
+ override def visit(node: FencedCodeBlock) = count(node, maxLen, _ => node.unlink())
+ }),
+ new VisitHandler(classOf[BulletListItem], new Visitor[BulletListItem] {
+ override def visit(node: BulletListItem) = count(
+ node,
+ if (didUnlink) maxLen
+ else node.getSegments.map(_.length).reduceLeft(_ + _),
+ _ => {
+ node.unlink()
+ didUnlink = true // unlink all following bullets
+ }
+ )
+ }),
+ new VisitHandler(classOf[OrderedListItem], new Visitor[OrderedListItem] {
+ override def visit(node: OrderedListItem) = count(
+ node,
+ if (didUnlink) maxLen
+ else node.getSegments.map(_.length).reduceLeft(_ + _),
+ _ => {
+ node.unlink()
+ didUnlink = true // unlink all following bullets
+ }
+ )
+ })
+ )
+
+ nodeVisitor.visit(node)
+ node
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala
new file mode 100644
index 000000000..176dab569
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/WikiParser.scala
@@ -0,0 +1,549 @@
+package dotty.tools.dottydoc
+package model
+package comment
+
+import dotty.tools.dotc.core.Contexts.Context
+import dotty.tools.dotc.util.Positions._
+import dotty.tools.dotc.core.Symbols._
+import dotty.tools.dotc.config.Printers.dottydoc
+import util.MemberLookup
+import scala.collection.mutable
+
+import Regexes._
+import model.internal._
+
+/** Original wikiparser from NSC
+ * @author Ingo Maier
+ * @author Manohar Jonnalagedda
+ * @author Gilles Dubochet
+ */
+private[comment] final class WikiParser(
+ entity: Entity,
+ packages: Map[String, Package],
+ val buffer: String,
+ pos: Position,
+ site: Symbol
+) extends CharReader(buffer) with MemberLookup { wiki =>
+ var summaryParsed = false
+
+ def document(): Body = {
+ val blocks = new mutable.ListBuffer[Block]
+ while (char != endOfText)
+ blocks += block()
+ Body(blocks.toList)
+ }
+
+ /* BLOCKS */
+
+ /** {{{ block ::= code | title | hrule | listBlock | para }}} */
+ def block(): Block = {
+ if (checkSkipInitWhitespace("{{{"))
+ code()
+ else if (checkSkipInitWhitespace('='))
+ title()
+ else if (checkSkipInitWhitespace("----"))
+ hrule()
+ else if (checkList)
+ listBlock
+ else {
+ para()
+ }
+ }
+
+ /** listStyle ::= '-' spc | '1.' spc | 'I.' spc | 'i.' spc | 'A.' spc | 'a.' spc
+ * Characters used to build lists and their constructors */
+ protected val listStyles = Map[String, (Seq[Block] => Block)](
+ "- " -> ( UnorderedList(_) ),
+ "1. " -> ( OrderedList(_,"decimal") ),
+ "I. " -> ( OrderedList(_,"upperRoman") ),
+ "i. " -> ( OrderedList(_,"lowerRoman") ),
+ "A. " -> ( OrderedList(_,"upperAlpha") ),
+ "a. " -> ( OrderedList(_,"lowerAlpha") )
+ )
+
+ /** Checks if the current line is formed with more than one space and one the listStyles */
+ def checkList =
+ (countWhitespace > 0) && (listStyles.keys exists { checkSkipInitWhitespace(_) })
+
+ /** {{{
+ * nListBlock ::= nLine { mListBlock }
+ * nLine ::= nSpc listStyle para '\n'
+ * }}}
+ * Where n and m stand for the number of spaces. When `m > n`, a new list is nested. */
+ def listBlock(): Block = {
+
+ /** Consumes one list item block and returns it, or None if the block is
+ * not a list or a different list. */
+ def listLine(indent: Int, style: String): Option[Block] =
+ if (countWhitespace > indent && checkList)
+ Some(listBlock)
+ else if (countWhitespace != indent || !checkSkipInitWhitespace(style))
+ None
+ else {
+ jumpWhitespace()
+ jump(style)
+ val p = Paragraph(getInline(isInlineEnd = false))
+ blockEnded("end of list line ")
+ Some(p)
+ }
+
+ /** Consumes all list item blocks (possibly with nested lists) of the
+ * same list and returns the list block. */
+ def listLevel(indent: Int, style: String): Block = {
+ val lines = mutable.ListBuffer.empty[Block]
+ var line: Option[Block] = listLine(indent, style)
+ while (line.isDefined) {
+ lines += line.get
+ line = listLine(indent, style)
+ }
+ val constructor = listStyles(style)
+ constructor(lines)
+ }
+
+ val indent = countWhitespace
+ val style = (listStyles.keys find { checkSkipInitWhitespace(_) }).getOrElse(listStyles.keys.head)
+ listLevel(indent, style)
+ }
+
+ def code(): Block = {
+ jumpWhitespace()
+ jump("{{{")
+ val str = readUntil("}}}")
+ if (char == endOfText)
+ reportError(pos, "unclosed code block")
+ else
+ jump("}}}")
+ blockEnded("code block")
+ Code(normalizeIndentation(str))
+ }
+
+ /** {{{ title ::= ('=' inline '=' | "==" inline "==" | ...) '\n' }}} */
+ def title(): Block = {
+ jumpWhitespace()
+ val inLevel = repeatJump('=')
+ val text = getInline(check("=" * inLevel))
+ val outLevel = repeatJump('=', inLevel)
+ if (inLevel != outLevel)
+ reportError(pos, "unbalanced or unclosed heading")
+ blockEnded("heading")
+ Title(text, inLevel)
+ }
+
+ /** {{{ hrule ::= "----" { '-' } '\n' }}} */
+ def hrule(): Block = {
+ jumpWhitespace()
+ repeatJump('-')
+ blockEnded("horizontal rule")
+ HorizontalRule()
+ }
+
+ /** {{{ para ::= inline '\n' }}} */
+ def para(): Block = {
+ val p =
+ if (summaryParsed)
+ Paragraph(getInline(isInlineEnd = false))
+ else {
+ val s = summary()
+ val r =
+ if (checkParaEnded()) List(s) else List(s, getInline(isInlineEnd = false))
+ summaryParsed = true
+ Paragraph(Chain(r))
+ }
+ while (char == endOfLine && char != endOfText)
+ nextChar()
+ p
+ }
+
+ /* INLINES */
+
+ val OPEN_TAG = "^<([A-Za-z]+)( [^>]*)?(/?)>$".r
+ val CLOSE_TAG = "^</([A-Za-z]+)>$".r
+ private def readHTMLFrom(begin: HtmlTag): String = {
+ val list = mutable.ListBuffer.empty[String]
+ val stack = mutable.ListBuffer.empty[String]
+
+ begin.close match {
+ case Some(HtmlTag(CLOSE_TAG(s))) =>
+ stack += s
+ case _ =>
+ return ""
+ }
+
+ do {
+ val str = readUntil { char == safeTagMarker || char == endOfText }
+ nextChar()
+
+ list += str
+
+ str match {
+ case OPEN_TAG(s, _, standalone) => {
+ if (standalone != "/") {
+ stack += s
+ }
+ }
+ case CLOSE_TAG(s) => {
+ if (s == stack.last) {
+ stack.remove(stack.length-1)
+ }
+ }
+ case _ => ;
+ }
+ } while (stack.length > 0 && char != endOfText)
+
+ list mkString ""
+ }
+
+ def getInline(isInlineEnd: => Boolean): Inline = {
+
+ def inline0(): Inline = {
+ if (char == safeTagMarker) {
+ val tag = htmlTag()
+ HtmlTag(tag.data + readHTMLFrom(tag))
+ }
+ else if (check("'''")) bold()
+ else if (check("''")) italic()
+ else if (check("`")) monospace()
+ else if (check("__")) underline()
+ else if (check("^")) superscript()
+ else if (check(",,")) subscript()
+ else if (check("[[")) link()
+ else {
+ val str = readUntil {
+ char == safeTagMarker ||
+ check("''") ||
+ char == '`' ||
+ check("__") ||
+ char == '^' ||
+ check(",,") ||
+ check("[[") ||
+ isInlineEnd ||
+ checkParaEnded ||
+ char == endOfLine
+ }
+ Text(str)
+ }
+ }
+
+ val inlines: List[Inline] = {
+ val iss = mutable.ListBuffer.empty[Inline]
+ iss += inline0()
+ while (!isInlineEnd && !checkParaEnded) {
+ val skipEndOfLine = if (char == endOfLine) {
+ nextChar()
+ true
+ } else {
+ false
+ }
+
+ val current = inline0()
+ (iss.last, current) match {
+ case (Text(t1), Text(t2)) if skipEndOfLine =>
+ iss.update(iss.length - 1, Text(t1 + endOfLine + t2))
+ case (i1, i2) if skipEndOfLine =>
+ iss ++= List(Text(endOfLine.toString), i2)
+ case _ => iss += current
+ }
+ }
+ iss.toList
+ }
+
+ inlines match {
+ case Nil => Text("")
+ case i :: Nil => i
+ case is => Chain(is)
+ }
+
+ }
+
+ def htmlTag(): HtmlTag = {
+ jump(safeTagMarker)
+ val read = readUntil(safeTagMarker)
+ if (char != endOfText) jump(safeTagMarker)
+ HtmlTag(read)
+ }
+
+ def bold(): Inline = {
+ jump("'''")
+ val i = getInline(check("'''"))
+ jump("'''")
+ Bold(i)
+ }
+
+ def italic(): Inline = {
+ jump("''")
+ val i = getInline(check("''"))
+ jump("''")
+ Italic(i)
+ }
+
+ def monospace(): Inline = {
+ jump("`")
+ val i = getInline(check("`"))
+ jump("`")
+ Monospace(i)
+ }
+
+ def underline(): Inline = {
+ jump("__")
+ val i = getInline(check("__"))
+ jump("__")
+ Underline(i)
+ }
+
+ def superscript(): Inline = {
+ jump("^")
+ val i = getInline(check("^"))
+ if (jump("^")) {
+ Superscript(i)
+ } else {
+ Chain(Seq(Text("^"), i))
+ }
+ }
+
+ def subscript(): Inline = {
+ jump(",,")
+ val i = getInline(check(",,"))
+ jump(",,")
+ Subscript(i)
+ }
+
+ def summary(): Inline = {
+ val i = getInline(checkSentenceEnded())
+ Summary(
+ if (jump("."))
+ Chain(List(i, Text(".")))
+ else
+ i
+ )
+ }
+
+ def link(): Inline = {
+ val SchemeUri = """([a-z]+:.*)""".r
+ jump("[[")
+ val parens = 2 + repeatJump('[')
+ val stop = "]" * parens
+ val target = readUntil { check(stop) || isWhitespaceOrNewLine(char) }
+ val title =
+ if (!check(stop)) Some({
+ jumpWhitespaceOrNewLine()
+ getInline(check(stop))
+ })
+ else None
+ jump(stop)
+
+ (target, title) match {
+ case (SchemeUri(uri), optTitle) =>
+ Link(uri, optTitle getOrElse Text(uri))
+ case (qualName, optTitle) =>
+ makeEntityLink(entity, packages, optTitle getOrElse Text(target), target)
+ }
+ }
+
+ /* UTILITY */
+
+ /** {{{ eol ::= { whitespace } '\n' }}} */
+ def blockEnded(blockType: String): Unit = {
+ if (char != endOfLine && char != endOfText) {
+ reportError(pos, "no additional content on same line after " + blockType)
+ jumpUntil(endOfLine)
+ }
+ while (char == endOfLine)
+ nextChar()
+ }
+
+ /**
+ * Eliminates the (common) leading spaces in all lines, based on the first line
+ * For indented pieces of code, it reduces the indent to the least whitespace prefix:
+ * {{{
+ * indented example
+ * another indented line
+ * if (condition)
+ * then do something;
+ * ^ this is the least whitespace prefix
+ * }}}
+ */
+ def normalizeIndentation(_code: String): String = {
+
+ val code = _code.replaceAll("\\s+$", "").dropWhile(_ == '\n') // right-trim + remove all leading '\n'
+ val lines = code.split("\n")
+
+ // maxSkip - size of the longest common whitespace prefix of non-empty lines
+ val nonEmptyLines = lines.filter(_.trim.nonEmpty)
+ val maxSkip = if (nonEmptyLines.isEmpty) 0 else nonEmptyLines.map(line => line.prefixLength(_ == ' ')).min
+
+ // remove common whitespace prefix
+ lines.map(line => if (line.trim.nonEmpty) line.substring(maxSkip) else line).mkString("\n")
+ }
+
+ def checkParaEnded(): Boolean = {
+ (char == endOfText) ||
+ ((char == endOfLine) && {
+ val poff = offset
+ nextChar() // read EOL
+ val ok = {
+ checkSkipInitWhitespace(endOfLine) ||
+ checkSkipInitWhitespace('=') ||
+ checkSkipInitWhitespace("{{{") ||
+ checkList ||
+ checkSkipInitWhitespace('\u003D')
+ }
+ offset = poff
+ ok
+ })
+ }
+
+ def checkSentenceEnded(): Boolean = {
+ (char == '.') && {
+ val poff = offset
+ nextChar() // read '.'
+ val ok = char == endOfText || char == endOfLine || isWhitespace(char)
+ offset = poff
+ ok
+ }
+ }
+
+ def reportError(pos: Position, message: String) =
+ dottydoc.println(s"$pos: $message")
+}
+
+sealed class CharReader(buffer: String) { reader =>
+
+ var offset: Int = 0
+ def char: Char =
+ if (offset >= buffer.length) endOfText else buffer charAt offset
+
+ final def nextChar() =
+ offset += 1
+
+ final def check(chars: String): Boolean = {
+ val poff = offset
+ val ok = jump(chars)
+ offset = poff
+ ok
+ }
+
+ def checkSkipInitWhitespace(c: Char): Boolean = {
+ val poff = offset
+ jumpWhitespace()
+ val ok = jump(c)
+ offset = poff
+ ok
+ }
+
+ def checkSkipInitWhitespace(chars: String): Boolean = {
+ val poff = offset
+ jumpWhitespace()
+ val (ok0, chars0) =
+ if (chars.charAt(0) == ' ')
+ (offset > poff, chars substring 1)
+ else
+ (true, chars)
+ val ok = ok0 && jump(chars0)
+ offset = poff
+ ok
+ }
+
+ def countWhitespace: Int = {
+ var count = 0
+ val poff = offset
+ while (isWhitespace(char) && char != endOfText) {
+ nextChar()
+ count += 1
+ }
+ offset = poff
+ count
+ }
+
+ /* Jumpers */
+
+ /** Jumps a character and consumes it
+ * @return true only if the correct character has been jumped */
+ final def jump(ch: Char): Boolean = {
+ if (char == ch) {
+ nextChar()
+ true
+ }
+ else false
+ }
+
+ /** Jumps all the characters in chars, consuming them in the process.
+ * @return true only if the correct characters have been jumped
+ */
+ final def jump(chars: String): Boolean = {
+ var index = 0
+ while (index < chars.length && char == chars.charAt(index) && char != endOfText) {
+ nextChar()
+ index += 1
+ }
+ index == chars.length
+ }
+
+ final def repeatJump(c: Char, max: Int = Int.MaxValue): Int = {
+ var count = 0
+ while (jump(c) && count < max)
+ count += 1
+ count
+ }
+
+ final def jumpUntil(ch: Char): Int = {
+ var count = 0
+ while (char != ch && char != endOfText) {
+ nextChar()
+ count += 1
+ }
+ count
+ }
+
+ final def jumpUntil(pred: => Boolean): Int = {
+ var count = 0
+ while (!pred && char != endOfText) {
+ nextChar()
+ count += 1
+ }
+ count
+ }
+
+ def jumpWhitespace() = jumpUntil(!isWhitespace(char))
+
+ def jumpWhitespaceOrNewLine() = jumpUntil(!isWhitespaceOrNewLine(char))
+
+ /* Readers */
+ final def readUntil(c: Char): String = {
+ withRead {
+ while (char != c && char != endOfText) {
+ nextChar()
+ }
+ }
+ }
+
+ final def readUntil(chars: String): String = {
+ assert(chars.length > 0)
+ withRead {
+ val c = chars.charAt(0)
+ while (!check(chars) && char != endOfText) {
+ nextChar()
+ while (char != c && char != endOfText)
+ nextChar()
+ }
+ }
+ }
+
+ final def readUntil(pred: => Boolean): String = {
+ withRead {
+ while (char != endOfText && !pred) {
+ nextChar()
+ }
+ }
+ }
+
+ private def withRead(read: => Unit): String = {
+ val start = offset
+ read
+ buffer.substring(start, offset)
+ }
+
+ /* Chars classes */
+ def isWhitespace(c: Char) = c == ' ' || c == '\t'
+
+ def isWhitespaceOrNewLine(c: Char) = isWhitespace(c) || c == '\n'
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
index 52379f9ad..9cbd1f6c8 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
@@ -5,7 +5,7 @@ import comment._
import references._
import dotty.tools.dotc.core.Symbols.{ Symbol, NoSymbol }
-trait Entity {
+trait Entity { entity =>
def symbol: Symbol
def name: String
@@ -19,6 +19,21 @@ trait Entity {
def parent: Entity
+ def annotations: List[String]
+
+ def signature: String =
+ entity.name + (entity match {
+ case o: Object => "$"
+ case d: Def => d.paramLists.mkString
+ case _ => ""
+ })
+
+ def children: List[Entity with Members] = entity match {
+ case e: Entity with Members =>
+ e.members.collect { case e: Entity with Members if e.kind != "package" => e }
+ case _ => Nil
+ }
+
/** All parents from package level i.e. Package to Object to Member etc */
def parents: List[Entity] = parent match {
case NonEntity => Nil
@@ -38,13 +53,21 @@ trait SuperTypes {
trait Members {
def members: List[Entity]
+
+ def hasVisibleMembers: Boolean = members.exists {
+ case e: Entity with Modifiers => !(e.isPrivate || e.isProtected)
+ case e => true
+ }
}
trait Modifiers {
def modifiers: List[String]
- val isPrivate: Boolean =
+ def isPrivate: Boolean =
modifiers.contains("private")
+
+ def isProtected: Boolean =
+ modifiers.contains("protected")
}
trait TypeParams {
@@ -58,36 +81,50 @@ trait ReturnValue {
trait ParamList {
def list: List[NamedReference]
def isImplicit: Boolean
+
+ override def toString = list.map(_.title).mkString("(", ",", ")")
}
trait Constructors {
def constructors: List[List[ParamList]]
}
+trait Companion extends Entity {
+ def hasCompanion: Boolean = companionPath ne Nil
+
+ def companionPath: List[String]
+
+ def companionPath_=(xs: List[String]): Unit
+}
+
trait ImplicitlyAddedEntity extends Entity {
def implicitlyAddedFrom: Option[Reference]
}
-trait Package extends Entity with Members {
+trait Package extends Entity with Members with SuperTypes {
val kind = "package"
+}
- def children: List[Entity with Members]
+trait TypeAlias extends Entity with Modifiers {
+ val kind = "type"
+ def alias: Option[Reference]
+ def isAbstract: Boolean = !alias.isDefined
}
-trait Class extends Entity with Modifiers with TypeParams with Constructors with SuperTypes with Members {
+trait Class extends Entity with Modifiers with TypeParams with Constructors with SuperTypes with Members with Companion {
val kind = "class"
}
-trait CaseClass extends Entity with Modifiers with TypeParams with Constructors with SuperTypes with Members {
+trait CaseClass extends Entity with Modifiers with TypeParams with Constructors with SuperTypes with Members with Companion {
override val kind = "case class"
}
-trait Trait extends Entity with Modifiers with TypeParams with SuperTypes with Members {
+trait Trait extends Entity with Modifiers with TypeParams with SuperTypes with Members with Companion {
def traitParams: List[ParamList]
override val kind = "trait"
}
-trait Object extends Entity with Modifiers with SuperTypes with Members {
+trait Object extends Entity with Modifiers with SuperTypes with Members with Companion {
override val kind = "object"
}
@@ -96,21 +133,29 @@ trait Def extends Entity with Modifiers with TypeParams with ReturnValue with Im
def paramLists: List[ParamList]
}
-trait Val extends Entity with Modifiers with ReturnValue with ImplicitlyAddedEntity {
- val kind = "val"
-}
-
-trait Var extends Entity with Modifiers with ReturnValue {
- val kind = "var"
-}
+trait Val extends Entity with Modifiers with ReturnValue with ImplicitlyAddedEntity
-trait NonEntity extends Entity {
- val name = ""
- val symbol = NoSymbol
+sealed trait NonEntity extends Package with TypeAlias with Class with CaseClass with Trait with Object with Def with Val {
+ override val kind = ""
+ val annotations = Nil
+ val name = ""
+ val symbol = NoSymbol
val comment = None
- val path = Nil
- val kind = ""
- val parent = NonEntity
+ val path = Nil
+ val parent = NonEntity
+ val constructors = Nil
+ val paramLists = Nil
+ val implicitlyAddedFrom = None
+ val members = Nil
+ val modifiers = Nil
+ val reference = EmptyReference
+ val returnValue = EmptyReference
+ val superTypes = Nil
+ val typeParams = Nil
+ val traitParams = Nil
+ val alias = None
+ val companionPath = Nil
+ def companionPath_=(xs: List[String]) = ()
}
final case object NonEntity extends NonEntity
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
index 433431f1c..568b532b7 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
@@ -26,15 +26,27 @@ object factories {
.flagStrings.toList
.filter(_ != "<trait>")
.filter(_ != "interface")
+ .filter(_ != "case")
def path(sym: Symbol)(implicit ctx: Context): List[String] = sym match {
case sym if sym.name.decode.toString == "<root>" => Nil
case sym => path(sym.owner) :+ sym.name.show
}
+ def annotations(sym: Symbol)(implicit ctx: Context): List[String] =
+ sym.annotations.map(_.symbol.showFullName)
private val product = """Product[1-9][0-9]*""".r
+ def alias(t: Type)(implicit ctx: Context): Option[Reference] = {
+ val defn = ctx.definitions
+ t match {
+ case TypeBounds(low, high) if (low eq defn.NothingType) && (high eq defn.AnyType) =>
+ None
+ case t => Some(returnType(t))
+ }
+ }
+
def returnType(t: Type)(implicit ctx: Context): Reference = {
val defn = ctx.definitions
@@ -44,79 +56,78 @@ object factories {
}
def expandTpe(t: Type, params: List[Reference] = Nil): Reference = t match {
- case tl: PolyType =>
- //FIXME: should be handled correctly
- // example, in `Option`:
- //
- // {{{
- // def companion: GenericCompanion[collection.Iterable]
- // }}}
- //
- // Becomes: def companion: [+X0] -> collection.Iterable[X0]
- typeRef(tl.show + " (not handled)")
- case AppliedType(tycon, args) =>
+ case AppliedType(tycon, args) => {
val cls = tycon.typeSymbol
- if (tycon.isRepeatedParam)
- expandTpe(args.head)
- else if (defn.isFunctionClass(cls))
+
+ if (defn.isFunctionClass(cls))
FunctionReference(args.init.map(expandTpe(_, Nil)), expandTpe(args.last))
else if (defn.isTupleClass(cls))
TupleReference(args.map(expandTpe(_, Nil)))
else {
- val query = tycon.show
- val name = query.split("\\.").last
+ val query = cls.showFullName
+ val name = cls.name.show
typeRef(name, query, params = args.map(expandTpe(_, Nil)))
}
+ }
- case ref @ RefinedType(parent, rn, info) =>
- expandTpe(parent) //FIXME: will be a refined HK, aka class Foo[X] { def bar: List[X] } or similar
- case ref @ HKApply(tycon, args) =>
- expandTpe(tycon, args.map(expandTpe(_, params)))
- case TypeRef(_, n) =>
- val name = n.decode.toString.split("\\$").last
- typeRef(name, params = params)
- case ta: TypeAlias =>
- expandTpe(ta.alias.widenDealias)
- case OrType(left, right) =>
- OrTypeReference(expandTpe(left), expandTpe(right))
- case AndType(left, right) =>
- AndTypeReference(expandTpe(left), expandTpe(right))
- case tb @ TypeBounds(lo, hi) =>
+ case t: TypeRef => {
+ val cls = t.typeSymbol
+ typeRef(cls.name.show.split("\\$\\$").last, query = cls.showFullName, params = params)
+ }
+
+ case TypeBounds(lo, hi) =>
BoundsReference(expandTpe(lo), expandTpe(hi))
- case AnnotatedType(tpe, _) =>
- expandTpe(tpe)
+
+ case t: PolyParam =>
+ typeRef(t.paramName.show, params = params)
+
case ExprType(tpe) =>
expandTpe(tpe)
- case c: ConstantType =>
- ConstantReference(c.show)
- case tt: ThisType =>
- expandTpe(tt.underlying)
- case ci: ClassInfo =>
- val query = path(ci.typeSymbol).mkString(".")
- typeRef(ci.cls.name.show, query = query)
- case mt: MethodType =>
- expandTpe(mt.resultType)
- case pt: PolyType =>
- expandTpe(pt.resultType)
- case pp: PolyParam =>
- val paramName = pp.paramName.show
- val name =
- if (paramName.contains('$'))
- paramName.split("\\$\\$").last
- else paramName
-
- typeRef(name)
- case tr: TermRef =>
+
+ case t: ThisType =>
+ expandTpe(t.underlying)
+
+ case AnnotatedType(t, _) =>
+ expandTpe(t)
+
+ case t: MethodType =>
+ expandTpe(t.finalResultType)
+
+ case t: TermRef => {
/** A `TermRef` appears in the return type in e.g:
* ```
* def id[T](t: T): t.type = t
* ```
*/
- val name = tr.show
- if (!name.endsWith(".type"))
- ctx.warning(s"unhandled return type found: $tr")
+ typeRef(t.name.show + ".type", params = params)
+ }
+
+ case ci: ClassInfo =>
+ typeRef(ci.cls.name.show, query = ci.typeSymbol.showFullName)
+
+ case tl: PolyType => {
+ // FIXME: should be handled correctly
+ // example, in `Option`:
+ //
+ // ```scala
+ // def companion: GenericCompanion[collection.Iterable]
+ // ```
+ //
+ // Becomes: def companion: [+X0] -> collection.Iterable[X0]
+ typeRef(tl.show + " (not handled)")
+ }
- typeRef(name, params = params)
+ case OrType(left, right) =>
+ OrTypeReference(expandTpe(left), expandTpe(right))
+
+ case AndType(left, right) =>
+ AndTypeReference(expandTpe(left), expandTpe(right))
+
+ case c: ConstantType =>
+ ConstantReference(c.value.show)
+
+ case ref @ RefinedType(parent, rn, info) =>
+ expandTpe(parent) //FIXME: will be a refined HK, aka class Foo[X] { def bar: List[X] } or similar
}
expandTpe(t)
@@ -164,9 +175,15 @@ object factories {
)
}, mt.isImplicit) :: paramLists(mt.resultType)
- case annot: AnnotatedType => paramLists(annot.tpe)
+ case mp: MethodParam =>
+ paramLists(mp.underlying)
+
+ case annot: AnnotatedType =>
+ paramLists(annot.tpe)
+
case (_: PolyParam | _: RefinedType | _: TypeRef | _: ThisType |
- _: ExprType | _: OrType | _: AndType | _: HKApply | _: TermRef) =>
+ _: ExprType | _: OrType | _: AndType | _: HKApply |
+ _: TermRef | _: ConstantType) =>
Nil // return types should not be in the paramlist
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala
index 09f642d0b..bf50c0232 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala
@@ -3,27 +3,41 @@ package model
import comment.Comment
import references._
-import dotty.tools.dotc.core.Symbols.Symbol
+import dotty.tools.dotc.core.Symbols.{ Symbol, NoSymbol }
object internal {
- trait Impl {
+ final case class PackageImpl(
+ var symbol: Symbol,
+ var annotations: List[String],
+ var name: String,
+ var members: List[Entity],
+ var path: List[String],
+ var superTypes: List[MaterializableLink] = Nil,
+ var comment: Option[Comment] = None,
var parent: Entity = NonEntity
+ ) extends Package
+
+ object EmptyPackage {
+ def apply(path: List[String], name: String): PackageImpl = {
+ PackageImpl(NoSymbol, Nil, name, Nil, path)
+ }
}
- final case class PackageImpl(
+ final case class TypeAliasImpl (
symbol: Symbol,
+ annotations: List[String],
+ modifiers: List[String],
name: String,
- var members: List[Entity],
path: List[String],
- var comment: Option[Comment] = None
- ) extends Package with Impl {
- def children: List[Entity with Members] =
- members.collect { case x: Entity with Members => x }
- }
+ alias: Option[Reference],
+ var comment: Option[Comment] = None,
+ var parent: Entity = NonEntity
+ ) extends TypeAlias
final case class ClassImpl(
symbol: Symbol,
+ annotations: List[String],
name: String,
members: List[Entity],
modifiers: List[String],
@@ -31,11 +45,14 @@ object internal {
typeParams: List[String] = Nil,
constructors: List[List[ParamList]] = Nil,
superTypes: List[MaterializableLink] = Nil,
- var comment: Option[Comment] = None
- ) extends Class with Impl
+ var comment: Option[Comment] = None,
+ var companionPath: List[String] = Nil,
+ var parent: Entity = NonEntity
+ ) extends Class
final case class CaseClassImpl(
symbol: Symbol,
+ annotations: List[String],
name: String,
members: List[Entity],
modifiers: List[String],
@@ -43,11 +60,14 @@ object internal {
typeParams: List[String] = Nil,
constructors: List[List[ParamList]] = Nil,
superTypes: List[MaterializableLink] = Nil,
- var comment: Option[Comment] = None
- ) extends CaseClass with Impl
+ var comment: Option[Comment] = None,
+ var companionPath: List[String] = Nil,
+ var parent: Entity = NonEntity
+ ) extends CaseClass
final case class TraitImpl(
symbol: Symbol,
+ annotations: List[String],
name: String,
members: List[Entity],
modifiers: List[String],
@@ -55,21 +75,27 @@ object internal {
typeParams: List[String] = Nil,
traitParams: List[ParamList] = Nil,
superTypes: List[MaterializableLink] = Nil,
- var comment: Option[Comment] = None
- ) extends Trait with Impl
+ var comment: Option[Comment] = None,
+ var companionPath: List[String] = Nil,
+ var parent: Entity = NonEntity
+ ) extends Trait
final case class ObjectImpl(
symbol: Symbol,
+ annotations: List[String],
name: String,
members: List[Entity],
modifiers: List[String],
path: List[String],
superTypes: List[MaterializableLink] = Nil,
- var comment: Option[Comment] = None
- ) extends Object with Impl
+ var comment: Option[Comment] = None,
+ var companionPath: List[String] = Nil,
+ var parent: Entity = NonEntity
+ ) extends Object
final case class DefImpl(
symbol: Symbol,
+ annotations: List[String],
name: String,
modifiers: List[String],
path: List[String],
@@ -77,18 +103,22 @@ object internal {
typeParams: List[String] = Nil,
paramLists: List[ParamList] = Nil,
var comment: Option[Comment] = None,
- implicitlyAddedFrom: Option[Reference] = None
- ) extends Def with Impl
+ implicitlyAddedFrom: Option[Reference] = None,
+ var parent: Entity = NonEntity
+ ) extends Def
final case class ValImpl(
symbol: Symbol,
+ annotations: List[String],
name: String,
modifiers: List[String],
path: List[String],
returnValue: Reference,
+ kind: String,
var comment: Option[Comment] = None,
- implicitlyAddedFrom: Option[Reference] = None
- ) extends Val with Impl
+ implicitlyAddedFrom: Option[Reference] = None,
+ var parent: Entity = NonEntity
+ ) extends Val
final case class ParamListImpl(
list: List[NamedReference],
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/java.scala b/doc-tool/src/dotty/tools/dottydoc/model/java.scala
deleted file mode 100644
index 410085061..000000000
--- a/doc-tool/src/dotty/tools/dottydoc/model/java.scala
+++ /dev/null
@@ -1,223 +0,0 @@
-package dotty.tools.dottydoc
-package model
-
-import comment._
-import references._
-
-object java {
- import scala.collection.JavaConverters._
- import _root_.java.util.{ Optional => JOptional, Map => JMap }
-
- implicit class JavaOption[A](val opt: Option[A]) extends AnyVal {
- def asJava: JOptional[A] =
- opt.map(a => JOptional.of(a)).getOrElse(JOptional.empty[A])
- }
-
- implicit class JavaComment(val cmt: Comment) extends AnyVal {
- def asJava: JMap[String, _] = Map(
- "body" -> cmt.body,
- "short" -> cmt.short,
- "authors" -> cmt.authors.asJava,
- "see" -> cmt.see.asJava,
- "result" -> cmt.result.asJava,
- "throws" -> cmt.throws.asJava,
- "valueParams" -> cmt.valueParams.asJava,
- "typeParams" -> cmt.typeParams.asJava,
- "version" -> cmt.version.asJava,
- "since" -> cmt.since.asJava,
- "todo" -> cmt.todo.asJava,
- "deprecated" -> cmt.deprecated.asJava,
- "note" -> cmt.note.asJava,
- "example" -> cmt.example.asJava,
- "constructor" -> cmt.constructor.asJava,
- "group" -> cmt.group.asJava,
- "groupDesc" -> cmt.groupDesc.asJava,
- "groupNames" -> cmt.groupNames.asJava,
- "groupPrio" -> cmt.groupPrio.asJava,
- "hideImplicitConversions" -> cmt.hideImplicitConversions.asJava
- ).asJava
- }
-
- implicit class JavaPackage(val ent: Package) extends AnyVal {
- def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "path" -> ent.path.asJava,
- "members" -> ent.members.map(_.asJava()).asJava,
- "comment" -> ent.comment.map(_.asJava).asJava
- ) ++ extras).asJava
- }
-
- implicit class JavaCaseClass(val ent: CaseClass) extends AnyVal {
- def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "members" -> ent.members.map(_.asJava()).asJava,
- "modifiers" -> ent.modifiers.asJava,
- "path" -> ent.path.asJava,
- "typeParams" -> ent.typeParams.asJava,
- "superTypes" -> ent.superTypes.map(_.asJava).asJava,
- "comment" -> ent.comment.map(_.asJava).asJava
- ) ++ extras).asJava
- }
-
- implicit class JavaClass(val ent: Class) extends AnyVal {
- def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "members" -> ent.members.map(_.asJava()).asJava,
- "modifiers" -> ent.modifiers.asJava,
- "path" -> ent.path.asJava,
- "typeParams" -> ent.typeParams.asJava,
- "superTypes" -> ent.superTypes.map(_.asJava).asJava,
- "comment" -> ent.comment.map(_.asJava).asJava
- ) ++ extras).asJava
- }
-
- implicit class JavaTrait(val ent: Trait) extends AnyVal {
- def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "members" -> ent.members.map(_.asJava()).asJava,
- "modifiers" -> ent.modifiers.asJava,
- "path" -> ent.path.asJava,
- "typeParams" -> ent.typeParams.asJava,
- "superTypes" -> ent.superTypes.map(_.asJava).asJava,
- "comment" -> ent.comment.map(_.asJava).asJava
- ) ++ extras).asJava
- }
-
- implicit class JavaObject(val ent: Object) extends AnyVal {
- def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = (Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "members" -> ent.members.map(_.asJava()).asJava,
- "modifiers" -> ent.modifiers.asJava,
- "path" -> ent.path.asJava,
- "superTypes" -> ent.superTypes.map(_.asJava).asJava,
- "comment" -> ent.comment.map(_.asJava).asJava
- ) ++ extras).asJava
- }
-
- implicit class JavaDef(val ent: Def) extends AnyVal {
- def asJava: JMap[String, _] = Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "modifiers" -> ent.modifiers.asJava,
- "path" -> ent.path.asJava,
- "returnValue" -> ent.returnValue.asJava,
- "typeParams" -> ent.typeParams.asJava,
- "paramLists" -> ent.paramLists.map(_.asJava).asJava,
- "comment" -> ent.comment.map(_.asJava).asJava,
- "implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava
- ).asJava
- }
-
- implicit class JavaVal(val ent: Val) extends AnyVal {
- def asJava: JMap[String, _] = Map(
- "kind" -> ent.kind,
- "name" -> ent.name,
- "modifiers" -> ent.modifiers.asJava,
- "path" -> ent.path.asJava,
- "returnValue" -> ent.returnValue.asJava,
- "comment" -> ent.comment.map(_.asJava).asJava,
- "implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava
- ).asJava
- }
-
- implicit class JavaParamList(val pl: ParamList) extends AnyVal {
- def asJava: JMap[String, _] = Map(
- "list" -> pl.list.map(_.asJava).asJava,
- "isImplicit" -> pl.isImplicit
- ).asJava
- }
-
- implicit class JavaReference(val ref: Reference) extends AnyVal {
- def asJava: JMap[String, _] = ref match {
- case TypeReference(title, tpeLink, paramLinks) => Map(
- "kind" -> "TypeReference",
- "title" -> title,
- "tpeLink" -> tpeLink.asJava,
- "paramLinks" -> paramLinks.map(_.asJava).asJava
- ).asJava
-
- case OrTypeReference(left, right) => Map(
- "kind" -> "OrTypeReference",
- "left" -> left.asJava,
- "right" -> right.asJava
- ).asJava
-
- case AndTypeReference(left, right) => Map(
- "kind" -> "AndTypeReference",
- "left" -> left.asJava,
- "right" -> right.asJava
- ).asJava
-
- case FunctionReference(args, returnValue) => Map(
- "kind" -> "FunctionReference",
- "args" -> args.map(_.asJava).asJava,
- "returnValue" -> returnValue
- ).asJava
-
- case TupleReference(args) => Map(
- "kind" -> "TupleReference",
- "args" -> args.map(_.asJava).asJava
- ).asJava
-
- case BoundsReference(low, high) => Map(
- "kind" -> "BoundsReference",
- "low" -> low.asJava,
- "hight" -> high.asJava
- ).asJava
-
- case NamedReference(title, ref, isByName, isRepeated) => Map(
- "kind" -> "NamedReference",
- "title" -> title,
- "ref" -> ref.asJava,
- "isByName" -> isByName,
- "isRepeated" -> isRepeated
- ).asJava
-
- case ConstantReference(title) => Map(
- "kind" -> "ConstantReference",
- "title" -> title
- ).asJava
- }
- }
-
- implicit class JavaMaterializableLink(val link: MaterializableLink) extends AnyVal {
- def asJava: JMap[String, _] = link match {
- case UnsetLink(title, query) => Map(
- "kind" -> "UnsetLink",
- "title" -> title,
- "query" -> query
- ).asJava
-
- case MaterializedLink(title, target) => Map(
- "kind" -> "MaterializedLink",
- "title" -> title,
- "target" -> target
- ).asJava
-
- case NoLink(title, target) => Map(
- "kind" -> "NoLink",
- "title" -> title,
- "target" -> target
- ).asJava
- }
- }
-
- implicit class JavaEntity(val ent: Entity) extends AnyVal {
- def asJava(extras: Map[String, _] = Map.empty): JMap[String, _] = parseEntity(ent, extras)
- }
-
- private def parseEntity(ent: Entity, extras: Map[String, _]): JMap[String, _] = ent match {
- case ent: Package => ent.asJava(extras)
- case ent: CaseClass => ent.asJava(extras)
- case ent: Class => ent.asJava(extras)
- case ent: Trait => ent.asJava(extras)
- case ent: Object => ent.asJava(extras)
- case ent: Def => ent.asJava
- case ent: Val => ent.asJava
- }
-}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/json.scala b/doc-tool/src/dotty/tools/dottydoc/model/json.scala
deleted file mode 100644
index 145728f8a..000000000
--- a/doc-tool/src/dotty/tools/dottydoc/model/json.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package dotty.tools.dottydoc
-package model
-
-import comment._
-import references._
-
-/** This object provides a protocol for serializing the package AST to JSON
- *
- * TODO: It might be a good ideat to represent the JSON better than just
- * serializing a big string-blob in the future.
- */
-object json {
- implicit class JsonString(val str: String) extends AnyVal {
- def json: String = {
- val cleanedString = str
- .replaceAll("\\\\","\\\\\\\\")
- .replaceAll("\\\"", "\\\\\"")
- .replaceAll("\n", "\\\\n")
-
- s""""$cleanedString""""
- }
- }
-
- implicit class JsonBoolean(val boo: Boolean) extends AnyVal {
- def json: String = if (boo) "true" else "false"
- }
-
- implicit class JsonComment(val cmt: Comment) extends AnyVal {
- def json: String =
- s"""{"body":${cmt.body.json},"short":${cmt.short.json},"authors":${cmt.authors.map(_.json).mkString("[",",","]")},"see":${cmt.see.map(_.json).mkString("[",",","]")},${cmt.result.map(res => s""""result":${res.json},""").getOrElse("")}"throws":${cmt.throws.map { case (k, v) => s"${k.json}:${v.json}" }.mkString("{",",","}")},"valueParams":${cmt.valueParams.map { case (k, v) => s"${k.json}:${v.json}"}.mkString("{",",","}")},"typeParams":${cmt.typeParams.map { case (k, v) => s"${k.json}:${v.json}"}.mkString("{",",","}")},${cmt.version.map(x => s""""version":${x.json},""").getOrElse("")}${cmt.since.map(x => s""""since":${x.json},""").getOrElse("")}"todo":${cmt.todo.map(_.json).mkString("[",",","]")},${cmt.deprecated.map(x => s""""deprecated":${x.json},""").getOrElse("")}"note":${cmt.note.map(_.json).mkString("[",",","]")},"example":${cmt.example.map(_.json).mkString("[",",","]")},${cmt.constructor.map(x => s""""constructor":${x.json},""").getOrElse("")}${cmt.group.map(x => s""""group":${x.json},""").getOrElse("")}"groupDesc":${cmt.groupDesc.map { case (k, v) => s"${k.json}:${v.json}"}.mkString("{",",","}")},"groupNames":${cmt.groupNames.map { case (k, v) => s"${k.json}:${v.json}"}.mkString("{",",","}")},"groupPrio":${cmt.groupPrio.map { case (k, v) => s"${k.json}:${v.json}"}.mkString("{",",","}")},"hideImplicitConversions":${cmt.hideImplicitConversions.map(_.json).mkString("[",",","]")}}"""
- }
-
- implicit class LinkJson(val link: MaterializableLink) extends AnyVal {
- def json: String = {
- val (secondTitle, secondValue, kind) = link match {
- case ul: UnsetLink => ("query".json, ul.query.json, "UnsetLink".json)
- case ml: MaterializedLink => ("target".json, ml.target.json, "MaterializedLink".json)
- case nl: NoLink => ("target".json, nl.target.json, "NoLink".json)
- }
- s"""{"title":${link.title.json},$secondTitle:${secondValue},"kind":$kind}"""
- }
- }
-
- implicit class ParamListJson(val plist: ParamList) extends AnyVal {
- def json: String =
- s"""{"list":${plist.list.map(_.json).mkString("[",",","]")},"isImplicit":${plist.isImplicit.json}}"""
- }
-
- private def refToJson(ref: Reference): String = ref match {
- case ref: TypeReference =>
- s"""{"title":${ref.title.json},"tpeLink":${ref.tpeLink.json},"paramLinks":${ref.paramLinks.map(_.json).mkString("[",",","]")},"kind":"TypeReference"}"""
- case ref: AndTypeReference =>
- s"""{"left":${refToJson(ref.left)},"right":${refToJson(ref.right)},"kind":"AndTypeReference"}"""
- case ref: OrTypeReference =>
- s"""{"left":${refToJson(ref.left)},"right":${refToJson(ref.right)},"kind":"OrTypeReference"}"""
- case ref: BoundsReference =>
- s"""{"low":${refToJson(ref.low)},"high":${refToJson(ref.high)},"kind":"BoundsReference"}"""
- case ref: NamedReference =>
- s"""{"title":${ref.title.json},"ref":${refToJson(ref.ref)},"isByName":${ref.isByName.json},"isRepeated":${ref.isRepeated.json},"kind":"NamedReference"}"""
- case ref: ConstantReference =>
- s"""{"title":${ref.title.json},"kind": "ConstantReference"}"""
- case ref: FunctionReference =>
- s"""{"args":${ref.args.map(refToJson).mkString("[",",","]")},"returnValue":${refToJson(ref.returnValue)},"kind": "FunctionReference"}"""
- case ref: TupleReference =>
- s"""{"args":${ref.args.map(refToJson).mkString("[",",","]")},"kind": "TupleReference"}"""
- }
- implicit class ReferenceJson(val ref: Reference) extends AnyVal { def json: String = refToJson(ref) }
-
- private def entToJson(ent: Entity): String = ent match {
- case ent: Package =>
- s"""{"name":${ent.name.json},"members":${ent.members.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}"kind":"package"}"""
- case ent: Class =>
- s"""{"name":${ent.name.json},"members":${ent.members.map(_.json).mkString("[",",","]")},"modifiers":${ent.modifiers.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},"typeParams":${ent.typeParams.map(_.json).mkString("[",",","]")},"constructors":${ent.constructors.map(xs => xs.map(_.json).mkString("[",",","]")).mkString("[",",","]")},"superTypes":${ent.superTypes.map(_.json).mkString("[",",","]")},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}"kind":"class"}"""
- case ent: CaseClass =>
- s"""{"name":${ent.name.json},"members":${ent.members.map(_.json).mkString("[",",","]")},"modifiers":${ent.modifiers.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},"typeParams":${ent.typeParams.map(_.json).mkString("[",",","]")},"constructors":${ent.constructors.map(xs => xs.map(_.json).mkString("[",",","]")).mkString("[",",","]")},"superTypes":${ent.superTypes.map(_.json).mkString("[",",","]")},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}"kind":"case class"}"""
- case ent: Trait =>
- s"""{"name":${ent.name.json},"members":${ent.members.map(_.json).mkString("[",",","]")},"modifiers":${ent.modifiers.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},"typeParams":${ent.typeParams.map(_.json).mkString("[",",","]")},"traitParams":${ent.traitParams.map(_.json).mkString("[",",","]")},"superTypes":${ent.superTypes.map(_.json).mkString("[",",","]")},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}"kind":"trait"}"""
- case ent: Object =>
- s"""{"name":${ent.name.json},"members":${ent.members.map(_.json).mkString("[",",","]")},"modifiers":${ent.modifiers.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},"superTypes":${ent.superTypes.map(_.json).mkString("[",",","]")},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}"kind":"object"}"""
- case ent: Def =>
- s"""{"name":${ent.name.json},"modifiers":${ent.modifiers.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},"returnValue":${ent.returnValue.json},"typeParams":${ent.typeParams.map(_.json).mkString("[",",","]")},"paramLists":${ent.paramLists.map(_.json).mkString("[",",","]")},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}${ent.implicitlyAddedFrom.fold("")(ref => s""""implicitlyAddedFrom":${ref.json},""")}"kind":"def"}"""
- case ent: Val =>
- s"""{"name":${ent.name.json},"modifiers":${ent.modifiers.map(_.json).mkString("[",",","]")},"path":${ent.path.map(_.json).mkString("[",",","]")},"returnValue":${ent.returnValue.json},${ent.comment.map(_.json).fold("")(cmt => s""""comment":$cmt,""")}${ent.implicitlyAddedFrom.fold("")(ref => s""""implicitlyAddedFrom":${ref.json},""")}"kind":"val"}"""
- }
- implicit class EntityJson(val ent: Entity) extends AnyVal { def json: String = entToJson(ent) }
- implicit class PackageJson(val pack: Package) extends AnyVal { def json: String = (pack: Entity).json }
-
- implicit class PackMapJson(val packs: collection.Map[String, Package]) extends AnyVal {
- def json: String = packs
- .map { case (k, v) => s"${k.json}: ${v.json}" }
- .mkString("{",",","}")
- }
-}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/references.scala b/doc-tool/src/dotty/tools/dottydoc/model/references.scala
index a28148fa7..a103347c1 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/references.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/references.scala
@@ -11,10 +11,28 @@ object references {
final case class BoundsReference(low: Reference, high: Reference) extends Reference
final case class NamedReference(title: String, ref: Reference, isByName: Boolean = false, isRepeated: Boolean = false) extends Reference
final case class ConstantReference(title: String) extends Reference
+ final case object EmptyReference extends Reference
/** Use MaterializableLink for entities that need be picklable */
sealed trait MaterializableLink { def title: String }
final case class UnsetLink(title: String, query: String) extends MaterializableLink
- final case class MaterializedLink(title: String, target: String) extends MaterializableLink
+ final case class MaterializedLink(title: String, target: String) extends MaterializableLink {
+ def this(title: String, target: Entity) = this(title, target match {
+ case target: Package =>
+ target.path.mkString("/") + "/index.html"
+ case _: TypeAlias | _: Def | _: Val =>
+ target.parent.path.mkString("/") + ".html#" + target.signature
+ case _ =>
+ target.path.mkString("/") + ".html"
+ })
+ }
final case class NoLink(title: String, target: String) extends MaterializableLink
+
+ object AndOrTypeReference {
+ def unapply(ref: Reference): Option[(Reference, String, Reference)] = ref match {
+ case OrTypeReference(left, right) => Some((left, "|", right))
+ case AndTypeReference(left, right) => Some((left, "&amp;", right))
+ case _ => None
+ }
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/BlogPost.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/BlogPost.scala
new file mode 100644
index 000000000..9268199ca
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/BlogPost.scala
@@ -0,0 +1,64 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import java.io.{ File => JFile }
+import java.util.{ List => JList, Map => JMap }
+
+import dotc.core.Contexts.Context
+import util.syntax._
+
+import MapOperations._
+
+/**
+ * A `BlogPost` represents the parsed posts from `./blog/_posts/`
+ * each post must be named according to the format
+ * `YYYY-MM-DD-title.{md,html}`
+ */
+class BlogPost(
+ val title: String,
+ val url: String,
+ val date: String,
+ val content: String,
+ firstParagraph: String,
+ val excerpt_separator: Option[String],
+ val categories: JList[String]
+) {
+ import scala.collection.JavaConverters._
+ lazy val excerpt: String = excerpt_separator match {
+ case Some(str) => content.split(str).head
+ case _ => firstParagraph
+ }
+
+ lazy val toMap: JMap[String, AnyRef] = Map(
+ "title" -> title,
+ "date" -> date,
+ "url" -> url,
+ "excerpt" -> excerpt,
+ "excerpt_separator" -> excerpt_separator.getOrElse(""),
+ "content" -> content,
+ "categories" -> categories
+ ).asJava
+}
+
+object BlogPost {
+ val extract = """(\d\d\d\d)-(\d\d)-(\d\d)-(.*)\.(md|html)""".r
+ def apply(file: JFile, page: Page)(implicit ctx: Context): Option[BlogPost] = {
+ def report(key: String, fallback: String = "") = {
+ ctx.docbase.error(s"couldn't find page.$key in ${file.getName}")
+ fallback
+ }
+
+ // Relying on the person using this class to pass a valid `file`
+ val extract(year, month, day, name, _) = file.getName
+ val title = page.yaml.getString("title").getOrElse(report("title", name))
+ val url = page.yaml.getString("url").getOrElse(report("url"))
+ val date = page.yaml.getString("date").getOrElse(s"$year-$month-$day 00:00:00")
+ val excerptSep = page.yaml.getString("excerpt_separator")
+ val categories = page.yaml.list("categories")
+
+ page.html.map { html =>
+ new BlogPost(title, url, date, html, page.firstParagraph, excerptSep, categories)
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala
new file mode 100644
index 000000000..066b23e0b
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/DefaultParams.scala
@@ -0,0 +1,90 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import model.{ Entity, Package, NonEntity }
+
+import java.util.{ HashMap, List => JList, Map => JMap }
+import scala.collection.JavaConverters._
+
+case class DefaultParams(
+ docs: JList[_],
+ originalDocs: Map[String, Package],
+ page: PageInfo,
+ site: SiteInfo,
+ sidebar: Sidebar,
+ entity: Entity = NonEntity
+) {
+ import model.JavaConverters._
+
+ def toMap: Map[String, AnyRef] = Map(
+ "docs" -> docs,
+
+ "originalDocs" -> originalDocs,
+
+ "page" -> Map(
+ "url" -> page.url,
+ "date" -> page.date,
+ "path" -> page.path
+ ),
+
+ "site" -> Map(
+ "baseurl" -> site.baseurl,
+ "posts" -> site.posts.map(_.toMap),
+ "project" -> site.projectTitle
+ ).asJava,
+
+ "sidebar" -> sidebar.titles.asJava,
+
+ "entity" -> entity.asJava()
+ )
+
+ def withPosts(posts: Array[BlogPost]): DefaultParams =
+ copy(site = SiteInfo(site.baseurl, site.projectTitle, posts))
+
+ def withUrl(url: String): DefaultParams =
+ copy(page = PageInfo(url))
+
+ def withEntity(e: model.Entity) = copy(entity = e)
+
+ def withDate(d: String) = copy(page = PageInfo(page.url, d))
+}
+
+case class PageInfo(url: String, date: String = "") {
+ val path: Array[String] = url.split('/').reverse.drop(1)
+}
+
+case class SiteInfo(baseurl: String, projectTitle: String, posts: Array[BlogPost])
+
+case class Sidebar(titles: List[Title])
+
+object Sidebar {
+ def apply(map: HashMap[String, AnyRef]): Option[Sidebar] = Option(map.get("sidebar")).map {
+ case list: JList[JMap[String, AnyRef]] @unchecked if !list.isEmpty =>
+ new Sidebar(list.asScala.map(Title.apply).flatMap(x => x).toList)
+ case _ => Sidebar.empty
+ }
+
+ def empty: Sidebar = Sidebar(Nil)
+}
+
+case class Title(title: String, url: Option[String], subsection: List[Title])
+
+object Title {
+ def apply(map: JMap[String, AnyRef]): Option[Title] = {
+ val title = Option(map.get("title")).collect {
+ case s: String => s
+ }
+ val url = Option(map.get("url")).collect {
+ case s: String => s
+ }
+ val subsection = Option(map.get("subsection")).collect {
+ case xs: JList[JMap[String, AnyRef]] @unchecked =>
+ xs.asScala.map(Title.apply).toList.flatMap(x => x)
+ }.getOrElse(Nil)
+
+ title.map {
+ case title: String => Title(title, url, subsection)
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/MapOperations.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/MapOperations.scala
new file mode 100644
index 000000000..9dd88cb67
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/MapOperations.scala
@@ -0,0 +1,25 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import java.util.{ List => JList, Map => JMap }
+
+/** A simple wrapper for Maps to impose a certain degree of typesafety */
+object MapOperations {
+ implicit class SaferMap(val map: Map[String, AnyRef]) extends AnyVal {
+ // `AnyRef` is actually `String | JList[String]`
+ def getString(str: String): Option[String] = map.get(str).flatMap {
+ case res: String => Some(res)
+ case _ => None
+ }
+
+ def getList(str: String): Option[JList[String]] = map.get(str).flatMap {
+ case res: JList[String] @unchecked => Some(res)
+ case _ => None
+ }
+
+ def string(str: String): String = getString(str).getOrElse("")
+ def list(str: String): JList[String] = getList(str).getOrElse(new java.util.ArrayList[String])
+ }
+}
+
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownCodeBlockVisitor.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownCodeBlockVisitor.scala
new file mode 100644
index 000000000..5aeffd0d5
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownCodeBlockVisitor.scala
@@ -0,0 +1,19 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import com.vladsch.flexmark.ast._
+import com.vladsch.flexmark.util.sequence.CharSubSequence
+
+object MarkdownCodeBlockVisitor {
+ def apply(node: Node): Unit =
+ new NodeVisitor(
+ new VisitHandler(classOf[FencedCodeBlock], new Visitor[FencedCodeBlock] {
+ override def visit(node: FencedCodeBlock): Unit = {
+ if (node.getOpeningMarker.length == 3)
+ node.setOpeningMarker(CharSubSequence.of("```scala"))
+ }
+ })
+ )
+ .visit(node)
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownLinkVisitor.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownLinkVisitor.scala
new file mode 100644
index 000000000..5216ee950
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/MarkdownLinkVisitor.scala
@@ -0,0 +1,42 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import com.vladsch.flexmark.ast._
+import com.vladsch.flexmark.util.sequence.CharSubSequence
+import model.{ Package, NonEntity, Val, Def, TypeAlias }
+import dottydoc.util.MemberLookup
+
+object MarkdownLinkVisitor {
+ private val EntityLink = """([^\.]+)(\.[^\.]+)*""".r
+ def apply(node: Node, docs: Map[String, Package], params: Map[String, AnyRef]): Unit =
+ (new NodeVisitor(
+ new VisitHandler(classOf[Link], new Visitor[Link] with MemberLookup {
+ override def visit(node: Link): Unit = {
+ val url = node.getUrl
+ if (url.endsWith(".md")) node.setUrl {
+ url.subSequence(0, url.lastIndexOf('.')).append(".html")
+ }
+ else if (EntityLink.unapplySeq(url.toString).isDefined) {
+ lookup(NonEntity, docs, url.toString).foreach { ent =>
+ val (path, suffix) = ent match {
+ case ent: Val => (ent.path.dropRight(1), ".html#" + ent.signature)
+ case ent: Def => (ent.path.dropRight(1), ".html#" + ent.signature)
+ case ent: TypeAlias => (ent.path.dropRight(1), ".html#" + ent.signature)
+ case ent: Package => (ent.path, "/index.html")
+ case ent => (ent.path, ".html")
+ }
+
+ params("site") match {
+ case map: java.util.Map[String, String] @unchecked => node.setUrl {
+ CharSubSequence.of(path.mkString(map.get("baseurl") + "/api/", "/", suffix))
+ }
+ case _ => ()
+ }
+ }
+ }
+ }
+ })
+ ))
+ .visit(node)
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala
new file mode 100644
index 000000000..4cbb57705
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Page.scala
@@ -0,0 +1,178 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+
+import dotc.util.SourceFile
+import com.vladsch.flexmark.html.HtmlRenderer
+import com.vladsch.flexmark.parser.Parser
+import com.vladsch.flexmark.ext.front.matter.AbstractYamlFrontMatterVisitor
+import java.util.{ Map => JMap, List => JList }
+import java.io.{ OutputStreamWriter, BufferedWriter }
+
+import io.VirtualFile
+import dotc.core.Contexts.Context
+import model.Package
+import scala.io.Codec
+
+/** When the YAML front matter cannot be parsed, this exception is thrown */
+case class IllegalFrontMatter(message: String) extends Exception(message)
+
+trait Page {
+ import scala.collection.JavaConverters._
+
+ /** Full map of includes, from name to contents */
+ def includes: Map[String, Include]
+
+ /** `SourceFile` with contents of page */
+ def sourceFile: SourceFile
+
+ /** String containing full unexpanded content of page */
+ final lazy val content: String = new String(sourceFile.content)
+
+ /** Parameters to page */
+ def params: Map[String, AnyRef]
+
+ /** Path to template */
+ def path: String
+
+ /** YAML front matter from the top of the file */
+ def yaml(implicit ctx: Context): Map[String, AnyRef] = {
+ if (_yaml eq null) initFields
+ _yaml
+ }
+
+ /** HTML generated from page */
+ def html(implicit ctx: Context): Option[String] = {
+ if (_html eq null) initFields
+ _html
+ }
+
+ /** First paragraph of page extracted from rendered HTML */
+ def firstParagraph(implicit ctx: Context): String = {
+ if (_html eq null) initFields
+
+ _html.map { _html =>
+ val sb = new StringBuilder
+ var pos = 0
+ // to handle nested paragraphs in non markdown code
+ var open = 0
+
+ while (pos < _html.length - 4) {
+ val str = _html.substring(pos, pos + 4)
+ val lstr = str.toLowerCase
+ sb append str.head
+
+ pos += 1
+ if (lstr.contains("<p>"))
+ open += 1
+ else if (lstr == "</p>") {
+ open -= 1
+ if (open == 0) {
+ pos = Int.MaxValue
+ sb append "/p>"
+ }
+ }
+ }
+
+ sb.toString
+ }
+ .getOrElse("")
+ }
+
+ protected def virtualFile(subSource: String): SourceFile = {
+ val virtualFile = new VirtualFile(path, path)
+ val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8"))
+ writer.write(subSource)
+ writer.close()
+
+ new SourceFile(virtualFile, Codec.UTF8)
+ }
+
+
+ protected[this] var _yaml: Map[String, AnyRef /* String | JList[String] */] = _
+ protected[this] var _html: Option[String] = _
+ protected[this] def initFields(implicit ctx: Context) = {
+ val md = Parser.builder(Site.markdownOptions).build.parse(content)
+ val yamlCollector = new AbstractYamlFrontMatterVisitor()
+ yamlCollector.visit(md)
+
+ _yaml = updatedYaml {
+ yamlCollector
+ .getData().asScala
+ .mapValues {
+ case xs if xs.size == 1 =>
+ val str = xs.get(0)
+ if (str.length > 0 && str.head == '"' && str.last == '"')
+ str.substring(1, str.length - 1)
+ else str
+ case xs => xs
+ }
+ .toMap
+ }
+
+ // YAML must start with "---" and end in either "---" or "..."
+ val withoutYaml = virtualFile(
+ if (content.startsWith("---\n")) {
+ val str =
+ content.lines
+ .drop(1)
+ .dropWhile(line => line != "---" && line != "...")
+ .drop(1).mkString("\n")
+
+ if (str.isEmpty) throw IllegalFrontMatter(content)
+ else str
+ }
+ else content
+ )
+
+ // make accessible via "{{ page.title }}" in templates
+ val page = Map("page" -> _yaml.asJava)
+ _html = LiquidTemplate(path, withoutYaml).render(params ++ page, includes)
+ }
+
+ /** Takes "page" from `params` map in case this is a second expansion, and
+ * removes "layout" from the parameters if it exists. We don't want to
+ * preserve the layout from the previously expanded template
+ */
+ private def updatedYaml(newYaml: Map[String, AnyRef]): Map[String, AnyRef] =
+ params
+ .get("page")
+ .flatMap {
+ case page: Map[String, AnyRef] @unchecked =>
+ Some(page - "layout" ++ newYaml)
+ case _ => None
+ }
+ .getOrElse(newYaml)
+}
+
+class HtmlPage(
+ val path: String,
+ val sourceFile: SourceFile,
+ val params: Map[String, AnyRef],
+ val includes: Map[String, Include]
+) extends Page
+
+class MarkdownPage(
+ val path: String,
+ val sourceFile: SourceFile,
+ val params: Map[String, AnyRef],
+ val includes: Map[String, Include],
+ docs: Map[String, Package]
+) extends Page {
+
+ override protected[this] def initFields(implicit ctx: Context) = {
+ super.initFields
+ _html = _html.map { _html =>
+ val md = Parser.builder(Site.markdownOptions).build.parse(_html)
+ // fix markdown linking
+ MarkdownLinkVisitor(md, docs, params)
+ MarkdownCodeBlockVisitor(md)
+ HtmlRenderer
+ .builder(Site.markdownOptions)
+ .escapeHtml(false)
+ .build()
+ .render(md)
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/ResourceFinder.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/ResourceFinder.scala
new file mode 100644
index 000000000..66d31fa18
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/ResourceFinder.scala
@@ -0,0 +1,16 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+trait ResourceFinder {
+ /** If, for some reason, the supplied default files cannot be found - this
+ * exception will be thrown in `layouts`.
+ */
+ final case class ResourceNotFoundException(message: String) extends Exception(message)
+
+ protected def getResource(r: String): String =
+ Option(getClass.getResourceAsStream(r)).map(scala.io.Source.fromInputStream)
+ .map(_.mkString)
+ .getOrElse(throw ResourceNotFoundException(r))
+
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala
new file mode 100644
index 000000000..6f1681a0a
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Site.scala
@@ -0,0 +1,409 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import java.nio.file.{ Files, FileSystems }
+import java.nio.file.StandardCopyOption.REPLACE_EXISTING
+import java.io.{ File => JFile, OutputStreamWriter, BufferedWriter, ByteArrayInputStream }
+import java.util.{ List => JList, Map => JMap, Arrays }
+import java.nio.file.Path
+import java.nio.charset.StandardCharsets
+
+import com.vladsch.flexmark.parser.ParserEmulationProfile
+import com.vladsch.flexmark.parser.Parser
+import com.vladsch.flexmark.ext.gfm.tables.TablesExtension
+import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension
+import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension
+import com.vladsch.flexmark.ext.emoji.EmojiExtension
+import com.vladsch.flexmark.ext.autolink.AutolinkExtension
+import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
+import com.vladsch.flexmark.ext.front.matter.YamlFrontMatterExtension
+import com.vladsch.flexmark.util.options.{ DataHolder, MutableDataSet }
+
+import dotc.core.Contexts.Context
+import dotc.util.SourceFile
+import model.Package
+import scala.io.{ Codec, Source }
+import io.{ AbstractFile, VirtualFile, File }
+import scala.collection.mutable.ArrayBuffer
+import util.syntax._
+
+case class Site(val root: JFile, val projectTitle: String, val documentation: Map[String, Package]) extends ResourceFinder {
+ /** Documentation serialized to java maps */
+ private val docs: JList[_] = {
+ import model.JavaConverters._
+ documentation.toJavaList
+ }
+
+ /** All files that are considered static in this context, this can be
+ * anything from CSS, JS to images and other files.
+ *
+ * @note files that are *not* considered static are files ending in a compilable
+ * extension.
+ */
+ def staticAssets(implicit ctx: Context): Array[JFile] = {
+ if (_staticAssets eq null) initFiles
+ _staticAssets
+ }
+
+ /** All files that are considered compilable assets in this context. This
+ * is mainly markdown and html files, but could include other files in the
+ * future.
+ *
+ * @note files that are considered compilable end in `.md` or `.html`
+ */
+ def compilableFiles(implicit ctx: Context): Array[JFile] = {
+ if (_compilableFiles eq null) initFiles
+ _compilableFiles
+ }
+
+ /** All files that are considered blogposts, currently this means that files have been placed in:
+ *
+ * ```
+ * ./blog/_posts/year-month-day-title.ext
+ * ```
+ *
+ * where `ext` is either markdown or html.
+ */
+ def blogposts(implicit ctx: Context): Array[JFile] = {
+ if (_blogposts eq null) initFiles
+ _blogposts
+ }
+
+ /** Sidebar created from `sidebar.yml` file in site root */
+ val sidebar: Sidebar =
+ root
+ .listFiles
+ .find(_.getName == "sidebar.yml")
+ .map("---\n" + Source.fromFile(_).mkString + "\n---")
+ .map(Yaml.apply)
+ .flatMap(Sidebar.apply)
+ .getOrElse(Sidebar.empty)
+
+ private[this] var _blogInfo: Array[BlogPost] = _
+ protected def blogInfo(implicit ctx: Context): Array[BlogPost] = {
+ if (_blogInfo eq null) {
+ _blogInfo =
+ blogposts
+ .flatMap { file =>
+ val BlogPost.extract(year, month, day, name, ext) = file.getName
+ val sourceFile = toSourceFile(file)
+ val params = defaultParams(file, 2).withUrl(s"/blog/$year/$month/$day/$name.html").toMap
+ val page =
+ if (ext == "md")
+ new MarkdownPage(file.getPath, sourceFile, params, includes, documentation)
+ else new HtmlPage(file.getPath, sourceFile, params, includes)
+ BlogPost(file, page)
+ }
+ .sortBy(_.date)
+ .reverse
+ }
+
+ _blogInfo
+ }
+
+ // FileSystem getter
+ private[this] val fs = FileSystems.getDefault
+
+ /** Create virtual file from string `sourceCode` */
+ private def stringToSourceFile(name: String, path: String, sourceCode: String): SourceFile = {
+ val virtualFile = new VirtualFile(name, path)
+ val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8"))
+ writer.write(sourceCode)
+ writer.close()
+
+ new SourceFile(virtualFile, Codec.UTF8)
+ }
+
+ /** Copy static files to `outDir` */
+ def copyStaticFiles(outDir: JFile = new JFile(root.getAbsolutePath + "/_site"))(implicit ctx: Context): this.type =
+ createOutput (outDir) {
+ // Copy user-defined static assets
+ staticAssets.foreach { asset =>
+ val target = mkdirs(fs.getPath(outDir.getAbsolutePath, stripRoot(asset)))
+ val source = mkdirs(fs.getPath(asset.getAbsolutePath))
+ Files.copy(source, target, REPLACE_EXISTING)
+ }
+
+ // Copy statics included in resources
+ Map(
+ "css/api-page.css" -> "/css/api-page.css",
+ "css/dottydoc.css" -> "/css/dottydoc.css",
+ "css/color-brewer.css" -> "/css/color-brewer.css",
+ "js/highlight.pack.js" -> "/js/highlight.pack.js"
+ )
+ .mapValues(getResource)
+ .foreach { case (path, resource) =>
+ val source = new ByteArrayInputStream(resource.getBytes(StandardCharsets.UTF_8))
+ val target = mkdirs(fs.getPath(outDir.getAbsolutePath, path))
+ Files.copy(source, target, REPLACE_EXISTING)
+ }
+ }
+
+ /** Generate default params included in each page */
+ private def defaultParams(pageLocation: JFile, additionalDepth: Int = 0): DefaultParams = {
+ import scala.collection.JavaConverters._
+ val pathFromRoot = stripRoot(pageLocation)
+ val baseUrl: String = {
+ val rootLen = root.getAbsolutePath.split('/').length
+ val assetLen = pageLocation.getAbsolutePath.split('/').length
+ "../" * (assetLen - rootLen - 1 + additionalDepth) + "."
+ }
+
+ DefaultParams(docs, documentation, PageInfo(pathFromRoot), SiteInfo(baseUrl, projectTitle, Array()), sidebar)
+ }
+
+ /* Creates output directories if allowed */
+ private def createOutput(outDir: JFile)(op: => Unit)(implicit ctx: Context): this.type = {
+ if (!outDir.isDirectory) outDir.mkdirs()
+ if (!outDir.isDirectory) ctx.docbase.error(s"couldn't create output folder: $outDir")
+ else op
+ this
+ }
+
+ /** Generate HTML for the API documentation */
+ def generateApiDocs(outDir: JFile = new JFile(root.getAbsolutePath + "/_site"))(implicit ctx: Context): this.type =
+ createOutput(outDir) {
+ def genDoc(e: model.Entity): Unit = {
+ ctx.docbase.echo(s"Generating doc page for: ${e.path.mkString(".")}")
+ // Suffix is index.html for packages and therefore the additional depth
+ // is increased by 1
+ val (suffix, offset) =
+ if (e.kind == "package") ("/index.html", -1)
+ else (".html", 0)
+
+ val target = mkdirs(fs.getPath(outDir.getAbsolutePath + "/api/" + e.path.mkString("/") + suffix))
+ val params = defaultParams(target.toFile, -1).withPosts(blogInfo).withEntity(e).toMap
+ val page = new HtmlPage("_layouts/api-page.html", layouts("api-page").content, params, includes)
+
+ render(page).foreach { rendered =>
+ val source = new ByteArrayInputStream(rendered.getBytes(StandardCharsets.UTF_8))
+ Files.copy(source, target, REPLACE_EXISTING)
+ }
+
+ // Generate docs for nested objects/classes:
+ e.children.foreach(genDoc)
+ }
+
+ documentation.values.foreach { pkg =>
+ genDoc(pkg)
+ pkg.children.foreach(genDoc)
+ }
+ }
+
+ /** Generate HTML files from markdown and .html sources */
+ def generateHtmlFiles(outDir: JFile = new JFile(root.getAbsolutePath + "/_site"))(implicit ctx: Context): this.type =
+ createOutput(outDir) {
+ compilableFiles.foreach { asset =>
+ val pathFromRoot = stripRoot(asset)
+ val sourceFile = toSourceFile(asset)
+ val params = defaultParams(asset).withPosts(blogInfo).toMap
+ val page =
+ if (asset.getName.endsWith(".md")) new MarkdownPage(pathFromRoot, sourceFile, params, includes, documentation)
+ else new HtmlPage(pathFromRoot, sourceFile, params, includes)
+
+ render(page).foreach { renderedPage =>
+ val source = new ByteArrayInputStream(renderedPage.getBytes(StandardCharsets.UTF_8))
+ val target = pathFromRoot.splitAt(pathFromRoot.lastIndexOf('.'))._1 + ".html"
+ val htmlTarget = mkdirs(fs.getPath(outDir.getAbsolutePath, target))
+ Files.copy(source, htmlTarget, REPLACE_EXISTING)
+ }
+ }
+ }
+
+ /** Generate blog from files in `blog/_posts` and output in `outDir` */
+ def generateBlog(outDir: JFile = new JFile(root.getAbsolutePath + "/_site"))(implicit ctx: Context): this.type =
+ createOutput(outDir) {
+ blogposts.foreach { file =>
+ val BlogPost.extract(year, month, day, name, ext) = file.getName
+ val sourceFile = toSourceFile(file)
+ val date = s"$year-$month-$day 00:00:00"
+ val params = defaultParams(file, 2).withPosts(blogInfo).withDate(date).toMap
+
+ // Output target
+ val target = mkdirs(fs.getPath(outDir.getAbsolutePath, "blog", year, month, day, name + ".html"))
+
+ val page =
+ if (ext == "md")
+ new MarkdownPage(target.toString, sourceFile, params, includes, documentation)
+ else
+ new HtmlPage(target.toString, sourceFile, params, includes)
+
+ render(page).map { rendered =>
+ val source = new ByteArrayInputStream(rendered.getBytes(StandardCharsets.UTF_8))
+ Files.copy(source, target, REPLACE_EXISTING)
+ }
+ }
+ }
+
+ /** Create directories and issue an error if could not */
+ private def mkdirs(path: Path)(implicit ctx: Context): path.type = {
+ val parent = path.getParent.toFile
+
+ if (!parent.isDirectory && !parent.mkdirs())
+ ctx.docbase.error(s"couldn't create directory: $parent")
+
+ path
+ }
+
+ /** This function allows the stripping of the path that leads up to root.
+ *
+ * ```scala
+ * stripRoot(new JFile("/some/root/dir/css/index.css"))
+ * // returns: dir/css/index.css
+ * // given that root is: /some/root
+ * ```
+ */
+ def stripRoot(f: JFile): String = {
+ val rootLen = root.getAbsolutePath.length + 1
+ f.getAbsolutePath.drop(rootLen)
+ }
+
+ // Initialization of `staticAssets` and `compilableAssets`, and `blogPosts`:
+ private[this] var _staticAssets: Array[JFile] = _
+ private[this] var _compilableFiles: Array[JFile] = _
+ private[this] var _blogposts: Array[JFile] = _
+
+ private[this] def initFiles(implicit ctx: Context) = {
+ // Split files between compilable and static assets
+ def splitFiles(f: JFile, assets: ArrayBuffer[JFile], comp: ArrayBuffer[JFile]): Unit = {
+ val name = f.getName
+ if (f.isDirectory) {
+ val name = f.getName
+ if (!name.startsWith("_") && name != "api") f.listFiles.foreach(splitFiles(_, assets, comp))
+ if (f.getName == "api") ctx.docbase.warn {
+ "the specified `/api` directory will not be used since it is needed for the api documentation"
+ }
+ }
+ else if (name.endsWith(".md") || name.endsWith(".html")) comp.append(f)
+ else assets.append(f)
+ }
+
+ // Collect posts from ./blog/_posts
+ def collectPosts(file: JFile): Option[JFile] = file.getName match {
+ case BlogPost.extract(year, month, day, name, ext) => Some(file)
+ case _ => None
+ }
+
+ val assets = new ArrayBuffer[JFile]
+ val comp = new ArrayBuffer[JFile]
+ splitFiles(root, assets, comp)
+ _staticAssets = assets.toArray
+ _compilableFiles = comp.toArray
+
+ _blogposts =
+ root
+ .listFiles
+ .find(dir => dir.getName == "blog" && dir.isDirectory)
+ .map(_.listFiles).getOrElse(Array.empty[JFile]) //FIXME: remove [JFile] once #1907 is fixed
+ .find(dir => dir.getName == "_posts" && dir.isDirectory)
+ .map(_.listFiles).getOrElse(Array.empty[JFile]) //FIXME: remove [JFile] once #1907 is fixed
+ .flatMap(collectPosts)
+ }
+
+ /** Files that define a layout then referred to by `layout: filename-no-ext`
+ * in yaml front-matter.
+ *
+ * The compiler will look in two locations, `<root>/_layouts/` and
+ * in the bundled jar file's resources `/_layouts`.
+ *
+ * If the user supplies a layout that has the same name as one of the
+ * defaults, the user-defined one will take precedence.
+ */
+ val layouts: Map[String, Layout] = {
+ val userDefinedLayouts =
+ root
+ .listFiles.find(d => d.getName == "_layouts" && d.isDirectory)
+ .map(collectFiles(_, f => f.endsWith(".md") || f.endsWith(".html")))
+ .getOrElse(Array.empty[JFile])
+ .map(f => (f.getName.substring(0, f.getName.lastIndexOf('.')), Layout(f.getPath, toSourceFile(f))))
+ .toMap
+
+ val defaultLayouts: Map[String, Layout] = Map(
+ "main" -> "/_layouts/main.html",
+ "sidebar" -> "/_layouts/sidebar.html",
+ "doc-page" -> "/_layouts/doc-page.html",
+ "api-page" -> "/_layouts/api-page.html",
+ "blog-page" -> "/_layouts/blog-page.html",
+ "index" -> "/_layouts/index.html"
+ ).map {
+ case (name, path) =>
+ (name, Layout(path, stringToSourceFile(name, path, getResource(path))))
+ }
+
+ defaultLayouts ++ userDefinedLayouts
+ }
+
+ /** Include files are allowed under the directory `_includes`. These files
+ * have to be compilable files and can be used with liquid includes:
+ *
+ * ```
+ * {% include "some-file" %}
+ * ```
+ *
+ * You can also use the `with` statement:
+ *
+ * ```
+ * {% include "some-file" with { key: value } %}
+ * ```
+ */
+ val includes: Map[String, Include] = {
+ val userDefinedIncludes =
+ root
+ .listFiles.find(d => d.getName == "_includes" && d.isDirectory)
+ .map(collectFiles(_, f => f.endsWith(".md") || f.endsWith(".html")))
+ .getOrElse(Array.empty[JFile])
+ .map(f => (f.getName, Include(f.getPath, toSourceFile(f))))
+ .toMap
+
+ val defaultIncludes: Map[String, Include] = Map(
+ "header.html" -> "/_includes/header.html",
+ "scala-logo.svg" -> "/_includes/scala-logo.svg",
+ "toc.html" -> "/_includes/toc.html"
+ ).map {
+ case (name, path) =>
+ (name, Include(path, stringToSourceFile(name, path, getResource(path))))
+ }
+
+ defaultIncludes ++ userDefinedIncludes
+ }
+
+ private def toSourceFile(f: JFile): SourceFile =
+ SourceFile(AbstractFile.getFile(new File(f)), Source.fromFile(f).toArray)
+
+ private def collectFiles(dir: JFile, includes: String => Boolean): Array[JFile] =
+ dir
+ .listFiles
+ .filter(f => includes(f.getName))
+
+ /** Render a page to html, the resulting string is the result of the complete
+ * expansion of the template with all its layouts and includes.
+ */
+ def render(page: Page, params: Map[String, AnyRef] = Map.empty)(implicit ctx: Context): Option[String] =
+ page.yaml.get("layout").flatMap(xs => layouts.get(xs.toString)) match {
+ case Some(layout) if page.html.isDefined =>
+ import scala.collection.JavaConverters._
+ val newParams = page.params ++ params ++ Map("page" -> page.yaml) ++ Map("content" -> page.html.get)
+ val expandedTemplate = new HtmlPage(layout.path, layout.content, newParams, includes)
+ render(expandedTemplate, params)
+ case _ =>
+ page.html
+ }
+}
+
+object Site {
+ val markdownOptions: DataHolder =
+ new MutableDataSet()
+ .setFrom(ParserEmulationProfile.KRAMDOWN.getOptions)
+ .set(Parser.EXTENSIONS, Arrays.asList(
+ TablesExtension.create(),
+ TaskListExtension.create(),
+ AutolinkExtension.create(),
+ AnchorLinkExtension.create(),
+ EmojiExtension.create(),
+ YamlFrontMatterExtension.create(),
+ StrikethroughExtension.create()
+ ))
+ .set(EmojiExtension.ROOT_IMAGE_PATH,
+ "https://github.global.ssl.fastly.net/images/icons/emoji/")
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala
new file mode 100644
index 000000000..498b21f57
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Template.scala
@@ -0,0 +1,112 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import scala.util.control.NonFatal
+
+import dotc.util.SourceFile
+import dotc.core.Contexts.Context
+import dotc.util.Positions.{ Position, NoPosition }
+import util.syntax._
+
+trait Template {
+ def path: String
+ def content: SourceFile
+ def show: String = new String(content.content)
+}
+
+case class TemplateRenderingError(path: String, ex: Throwable)
+extends Exception(s"error rendering $path, $ex")
+
+case class Layout(path: String, content: SourceFile) extends Template
+
+case class Include(path: String, content: SourceFile) extends Template
+
+case class LiquidTemplate(path: String, content: SourceFile) extends Template with ResourceFinder {
+ import scala.collection.JavaConverters._
+ import dotc.printing.Highlighting._
+ import liqp.Template
+ import liqp.filters.Filter
+ import liqp.parser.Flavor.JEKYLL
+ import java.util.{ HashMap, Map => JMap }
+ import filters._
+ import tags._
+
+ /** Register filters to static container */
+ Filter.registerFilter(new Reverse)
+ Filter.registerFilter(new First)
+
+ // For some reason, liqp rejects a straight conversion using `.asJava`
+ private def toJavaMap(map: Map[String, AnyRef]): HashMap[String, Object] =
+ map.foldLeft(new HashMap[String, Object]()) { case (map, (k, v)) =>
+ map.put(k, v)
+ map
+ }
+
+ private def protectedRender(op: => String)(implicit ctx: Context) = try {
+ Some(op)
+ } catch {
+ case NonFatal(ex) => {
+ // TODO: when we reimplement the liquid parser, this can go away. For now
+ // this is an OK approximation of what went wrong.
+ if ((ex.getCause eq null) || ex.getMessage.contains("exceeded the max amount of time")) {
+ ctx.docbase.error(
+ "unknown error occurred in " +
+ Blue(path).toString +
+ ", most likely incorrect usage of tag"
+ )
+ None
+ }
+ else ex.getCause match {
+ case mm: org.antlr.runtime.MismatchedTokenException => {
+ val unexpected = LiquidTemplate.token(mm.getUnexpectedType)
+ val expected = LiquidTemplate.token(mm.expecting)
+
+ ctx.error(
+ if (unexpected == "EOF")
+ s"unexpected end of file, expected: '$expected'"
+ else
+ s"unexpected token '$unexpected', expected: '$expected'",
+ content atPos Position(mm.index)
+ )
+
+ None
+ }
+ case ex => {
+ if (true || ctx.settings.debug.value)
+ throw ex
+
+ None
+ }
+ }
+ }
+ }
+
+ def render(params: Map[String, AnyRef], includes: Map[String, Include])(implicit ctx: Context): Option[String] =
+ protectedRender {
+ Template.parse(show, JEKYLL)
+ .`with`(ResourceInclude(params, includes))
+ .`with`(RenderReference(params))
+ .`with`(RenderLink(params))
+ .`with`(RenderTitle(params))
+ .`with`(Docstring(params))
+ .render(toJavaMap(params))
+ }
+}
+
+object LiquidTemplate {
+ import liqp.parser.LiquidParser
+
+ private val _tokens: Map[String, String] = Map(
+ "TagStart" -> "{%",
+ "TagEnd" -> "%}"
+ )
+
+ def token(i: Int): String =
+ if (i == -1) "EOF"
+ else if (i >= LiquidParser.tokenNames.length)
+ "non-existing token"
+ else _tokens
+ .get(LiquidParser.tokenNames(i))
+ .getOrElse(s"token $i")
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/Yaml.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/Yaml.scala
new file mode 100644
index 000000000..07bc27562
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/Yaml.scala
@@ -0,0 +1,23 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.core.`type`.TypeReference
+
+object Yaml {
+ import scala.collection.JavaConverters._
+ import java.util.HashMap
+ import java.io.ByteArrayInputStream
+
+ def apply(input: String): HashMap[String, AnyRef] = {
+ val is = new ByteArrayInputStream(input.getBytes("UTF-8"))
+ val mapper = new ObjectMapper(new YAMLFactory())
+
+ val typeRef: TypeReference[HashMap[String, AnyRef]] =
+ new TypeReference[HashMap[String, AnyRef]] {}
+
+ mapper.readValue(is, typeRef)
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/filters.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/filters.scala
new file mode 100644
index 000000000..1569d3873
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/filters.scala
@@ -0,0 +1,42 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import java.util.{ Map => JMap }
+
+import liqp.filters.Filter
+
+/** Custom liquid template filters */
+object filters {
+
+ /** Used to reverse arrays:
+ *
+ * ```html
+ * {% assign array = "1,2,3,4,5" | split: "," %}
+ * {{ array | reverse }}
+ * ```
+ */
+ final class Reverse extends Filter("reverse") {
+ override def apply(value: Any, params: AnyRef*): AnyRef = {
+ val array = super.asArray(value)
+ if (array.length == 0) null
+ else array.reverse
+ }
+ }
+
+ /** Used to get the first element of arrays and strings:
+ *
+ * ```html
+ * {% assign array = "1,2,3,4,5" | split: "," %}
+ * {{ array | first }}
+ * ```
+ * The above snippet will render "1"
+ */
+ final class First extends Filter("first") {
+ override def apply(value: Any, params: AnyRef*): AnyRef = value match {
+ case str: String if str.nonEmpty => str.charAt(0).toString
+ case xs: Array[String] if xs.nonEmpty => xs.head
+ case _ => null
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
new file mode 100644
index 000000000..cd2ea587d
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
@@ -0,0 +1,221 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import model.references._
+import dotc.core.Contexts.Context
+
+import liqp.tags.Tag
+import liqp.TemplateContext
+import liqp.nodes.LNode
+
+import java.util.{ Map => JMap }
+import model._
+import util.syntax._
+
+object tags {
+
+ sealed trait ParamConverter {
+ def params: Map[String, AnyRef]
+
+ private[this] var _baseurl: String = _
+ def baseurl(implicit ctx: Context): String = {
+ if (_baseurl eq null) {
+ _baseurl =
+ params.get("site").flatMap {
+ case map: JMap[String, String] @unchecked =>
+ Some(map.get("baseurl"))
+ case _ =>
+ None
+ }
+ .getOrElse {
+ ctx.docbase.warn(s"missing `baseurl` in: $params")
+ ""
+ }
+ }
+ _baseurl
+ }
+ }
+
+ /** Renders a `MaterializableLink` into a HTML anchor tag. If the link is
+ * `NoLink` it will just return a string with the link's title.
+ */
+ final case class RenderLink(params: Map[String, AnyRef])(implicit ctx: Context)
+ extends Tag("renderLink") with ParamConverter {
+ override def render(tctx: TemplateContext, nodes: LNode*): AnyRef = nodes(0).render(tctx) match {
+ case map: JMap[String, AnyRef] @unchecked =>
+ val link = map.get("scala")
+ if (link.isInstanceOf[MaterializableLink] && (link ne null))
+ renderLink(baseurl, link.asInstanceOf[MaterializableLink])
+ else if (link eq null)
+ null // Option[Reference] was None
+ else {
+ ctx.docbase.error(s"illegal argument: $link, to `renderLink` function")
+ null
+ }
+ case _ => null
+ }
+ }
+
+
+ private[this] def renderLink(baseurl: String, link: MaterializableLink)(implicit ctx: Context): String =
+ link match {
+ case MaterializedLink(title, target) =>
+ s"""<a href="$baseurl/api/$target">$title</a>"""
+ case _ => link.title
+ }
+
+ final case class RenderReference(params: Map[String, AnyRef])(implicit ctx: Context)
+ extends Tag("renderRef") with ParamConverter {
+
+ private def renderReference(ref: Reference): String = ref match {
+ case TypeReference(_, tpeLink, paramLinks) => {
+ if (paramLinks.nonEmpty) {
+ s"""|${renderLink(baseurl, tpeLink)}
+ |<span class="no-left no-right">[</span>
+ |${ paramLinks.map(renderReference).mkString("""<span class="">, </span>""") }
+ |<span class="no-left">]</span>""".stripMargin
+ }
+ else renderLink(baseurl, tpeLink)
+ }
+
+ case AndOrTypeReference(left, sep, right) =>
+ s"""${renderReference(left)}<span class="and-or-separator"> $sep </span>${renderReference(right)}"""
+
+ case FunctionReference(args, returnValue) => {
+ val params =
+ if (args.isEmpty) "<span>() =&gt; </span>"
+ else if (args.tail.isEmpty) renderReference(args.head) + """<span class="right-arrow"> =&gt; </span>"""
+ else args.map(renderReference).mkString("<span>(</span>", "<span>, </span>", "<span>) =&gt; </span>")
+
+ params + renderReference(returnValue)
+ }
+
+ case TupleReference(args) =>
+ s"""|<span class="no-right">(</span>
+ |${ args.map(renderReference).mkString("<span>, </span>") }
+ |<span class="no-left">)</span>""".stripMargin
+
+ case BoundsReference(low, high) =>
+ s"""${ renderReference(low) }<span class="bounds"> &lt;: </span>${ renderReference(high) }"""
+
+ case NamedReference(title, _, _, _) =>
+ ctx.docbase.error(s"received illegal named reference in rendering: $ref")
+ title
+
+ case ConstantReference(title) => title
+ }
+ override def render(tctx: TemplateContext, nodes: LNode*): AnyRef = nodes(0).render(tctx) match {
+ case map: JMap[String, AnyRef] @unchecked =>
+ val ref = map.get("scala")
+ if (ref.isInstanceOf[Reference] && (ref ne null)) renderReference(ref.asInstanceOf[Reference])
+ else if (ref eq null) null // Option[Reference] was None
+ else {
+ ctx.docbase.error(s"illegal argument: $ref, to `renderRef` function")
+ null
+ }
+ case _ => null
+ }
+ }
+
+ case class ResourceInclude(params: Map[String, AnyRef], includes: Map[String, Include])(implicit ctx: Context)
+ extends Tag("include") {
+ import scala.collection.JavaConverters._
+ val DefaultExtension = ".html"
+
+ override def render(tctx: TemplateContext, nodes: LNode*): AnyRef = {
+ val origInclude = asString(nodes(0).render(tctx))
+ val incResource = origInclude match {
+ case fileWithExt if fileWithExt.indexOf('.') > 0 => fileWithExt
+ case file => file + DefaultExtension
+ }
+
+ includes
+ .get(incResource)
+ .map { template =>
+ if (nodes.length > 1) tctx.put(origInclude, nodes(1).render(tctx))
+
+ LiquidTemplate(template.path, template.content)
+ .render(tctx.getVariables.asScala.toMap, includes)
+ .getOrElse("")
+ }
+ .getOrElse {
+ ctx.docbase.error(s"couldn't find include file '$origInclude'")
+ ""
+ }
+ }
+ }
+
+ /** Can be used to render the `sidebar.yml` entries, represented here as
+ * `Title`.
+ *
+ * ```html
+ * {% renderTitle title, parent %}
+ * ```
+ *
+ * The rendering currently works on depths up to 2. This means that each
+ * title can have a subsection with its own titles.
+ */
+ 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"""|<a class="toggle-children" onclick='$onclickFunction'>${t.title}</a>
+ |<ul id="${t.title}" class="${if (parent.toLowerCase == t.title.toLowerCase) "show" else "hide"}">
+ | ${t.subsection.map(renderTitle(_, parent)).mkString("<li>", "</li><li>", "</li>")}
+ |</ul>""".stripMargin
+ }
+ else if (t.url.isDefined) {
+ val url = t.url.get
+ s"""<a href="$baseurl/$url">${t.title}</a>"""
+ }
+ 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
+ }
+ }
+
+ override def render(ctx: TemplateContext, nodes: LNode*): AnyRef =
+ (nodes(0).render(ctx), nodes(1).render(ctx)) match {
+ case (t: Title, parent: String) => renderTitle(t, parent)
+ case _ => null
+ }
+ }
+
+ /** Allows the extraction of docstrings from the given path. E.g:
+ *
+ * ```html
+ * {% docstring "scala.collection.Seq" %}
+ * ```
+ *
+ * In Scaladoc, objects are denoted by a name ending in '$'. This means that
+ * a path that goes through, or targets an object need to appropriately
+ * intersperse these, e.g:
+ *
+ * ```html
+ * {% docstring "scala.collection.Seq$" %}
+ * ```
+ */
+ case class Docstring(params: Map[String, AnyRef]) extends Tag("docstring") {
+ private def find(xs: List[String], ent: Entity with Members): Option[Entity] = xs match {
+ case Nil => None
+ case x :: Nil =>
+ ent.members collect { case e: Entity with Members => e } find (_.path.last == x)
+ case x :: xs =>
+ ent.members collect { case e: Entity with Members => e } find (_.path.last == x) flatMap (find(xs, _))
+ }
+
+ override def render(ctx: TemplateContext, nodes: LNode*): AnyRef = nodes(0).render(ctx) match {
+ case query: String =>
+ params.get("originalDocs").collect {
+ case docs: Map[String, Package] @unchecked =>
+ val search = query.split("\\.")
+ if (search.isEmpty || !docs.contains(search.head)) null
+ else find(search.tail.toList, docs(search.head)).flatMap(_.comment.map(_.body)).getOrElse(null)
+ }.getOrElse(null)
+ case _ => null
+ }
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/MemberLookup.scala b/doc-tool/src/dotty/tools/dottydoc/util/MemberLookup.scala
index 40c775428..bb09a7090 100644
--- a/doc-tool/src/dotty/tools/dottydoc/util/MemberLookup.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/util/MemberLookup.scala
@@ -7,7 +7,6 @@ import dotc.core.Contexts.Context
import dotc.core.Flags
import dotc.core.Names._
import dotc.core.Symbols._
-import dotc.core.Types._
import dotc.core.Names._
import dotc.util.Positions._
import model.internal._
@@ -17,30 +16,25 @@ import model._
trait MemberLookup {
/** Performs a lookup based on the provided (pruned) query string
*
- * Will return a `Tooltip` if unsucessfull, otherwise a LinkToEntity or LinkToExternal
+ * Will return a `Tooltip` if unsucessfull, otherwise a LinkToEntity or
+ * LinkToExternal
*/
- def lookup(
- entity: Entity,
- packages: Map[String, Package],
- query: String,
- pos: Position
- ): LinkTo = {
- val notFound: LinkTo = Tooltip(query)
+ def lookup(entity: Entity, packages: Map[String, Package], query: String): Option[Entity] = {
+ val notFound: Option[Entity] = None
val querys = query.split("\\.").toList
/** Looks for the specified entity among `ent`'s members */
- def localLookup(ent: Entity with Members, searchStr: String): LinkTo =
+ def localLookup(ent: Entity with Members, searchStr: String): Option[Entity] =
ent
.members
.collect { case x if x.name == searchStr => x }
.sortBy(_.path.last)
.headOption
- .fold(notFound)(e => LinkToEntity(e))
/** Looks for an entity down in the structure, if the search list is Nil,
* the search stops
*/
- def downwardLookup(ent: Entity with Members, search: List[String]): LinkTo =
+ def downwardLookup(ent: Entity with Members, search: List[String]): Option[Entity] =
search match {
case Nil => notFound
case x :: Nil =>
@@ -48,7 +42,10 @@ trait MemberLookup {
case x :: xs =>
ent
.members
- .collect { case e: Entity with Members if e.name == x => e }
+ .collect {
+ case e: Entity with Members if e.name == x => e
+ case e: Entity with Members if e.name == x.init && x.last == '$' => e
+ }
.headOption
.fold(notFound)(e => downwardLookup(e, xs))
}
@@ -56,9 +53,9 @@ trait MemberLookup {
/** Finds package with longest matching name, then does downwardLookup in
* the package
*/
- def globalLookup: LinkTo = {
+ def globalLookup: Option[Entity] = {
def longestMatch(list: List[String]): List[String] =
- if (list == Nil) Nil
+ if (list eq Nil) Nil
else
packages
.get(list.mkString("."))
@@ -72,13 +69,14 @@ trait MemberLookup {
}
(querys, entity) match {
+ case (xs, NonEntity) => globalLookup
case (x :: Nil, e: Entity with Members) =>
localLookup(e, x)
case (x :: _, e: Entity with Members) if x == entity.name =>
downwardLookup(e, querys)
case (x :: xs, _) =>
if (xs.nonEmpty) globalLookup
- else lookup(entity, packages, "scala." + query, pos)
+ else lookup(entity, packages, "scala." + query)
}
}
@@ -86,7 +84,13 @@ trait MemberLookup {
entity: Entity,
packages: Map[String, Package],
title: Inline,
- pos: Position,
query: String
- ): EntityLink = EntityLink(title, lookup(entity, packages, query, pos))
+ ): EntityLink = {
+ val link =
+ lookup(entity, packages, query)
+ .map(LinkToEntity)
+ .getOrElse(Tooltip(query))
+
+ EntityLink(title, link)
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/OutputWriter.scala b/doc-tool/src/dotty/tools/dottydoc/util/OutputWriter.scala
deleted file mode 100644
index 2084e0a97..000000000
--- a/doc-tool/src/dotty/tools/dottydoc/util/OutputWriter.scala
+++ /dev/null
@@ -1,125 +0,0 @@
-package dotty.tools.dottydoc
-package util
-
-import dotty.tools.dotc.config.Printers.dottydoc
-
-import _root_.java.io.{
- File => JFile,
- PrintWriter => JPrintWriter,
- FileReader => JFileReader,
- BufferedInputStream,
- InputStream,
- InputStreamReader,
- FileOutputStream,
- BufferedOutputStream,
- FileNotFoundException
-}
-import _root_.java.net.URL
-import _root_.java.util.{ Map => JMap, List => JList }
-import model.{ Entity, Package }
-import model.json._
-import com.github.mustachejava.DefaultMustacheFactory
-import scala.collection.JavaConverters._
-
-class OutputWriter {
-
- def writeJava(packs: JMap[String, Package], outPath: String, template: URL, resources: JList[URL]): Unit = {
- write(packs.asScala, outPath, template, resources.asScala)
- }
-
- def write(packs: collection.Map[String, Package], outPath: String, template: URL, resources: Traversable[URL]): Unit = {
- // Write all packages to `outPath`
- for (pack <- packs.values) {
- println(s"""Writing '${pack.path.mkString(".")}'""")
- writeFile(
- expandTemplate(template, pack, outPath),
- outPath + pack.path.mkString("/", "/", "/"),
- "index.html")
-
- // Write all package children to outPath
- for {
- child <- pack.children
- if child.kind != "package"
- } {
- println(s"""Writing '${child.path.mkString(".")}'""")
- writeFile(
- expandTemplate(template, child, outPath),
- outPath + child.path.dropRight(1).mkString("/", "/", "/"),
- child.path.last + ".html")
- }
- }
-
- // Write full index to outPath
- val js = "Index = {}; Index.packages = " + packs.json + ";"
- println("Writing index.js...")
- writeFile(js, outPath + "/docassets/", "index.js")
-
- // Write resources to outPath
- println("Copying CSS/JS resources to destination...")
- assert(resources.nonEmpty)
-
- // TODO: splitting the URL by '/' and taking the last means that we don't
- // allow folders among the resources
- resources.foreach(url => copy(url.openStream, outPath, url.getFile.split("/").last))
-
- println("Done writing static material, building js-app")
- }
-
- def writeJsonJava(index: JMap[String, Package], outputDir: String): Unit =
- writeJson(index.asScala, outputDir)
-
- def writeJson(index: collection.Map[String, Package], outputDir: String): Unit =
- writeFile(index.json, outputDir + "/", "index.json")
-
- def expandTemplate(template: URL, entity: Entity, outPath: String): String = try {
- import model.json._
- import model.java._
-
- val inputStream = template.openStream
- val writer = new _root_.java.io.StringWriter()
- val mf = new DefaultMustacheFactory()
-
- def toRoot = "../" * (entity.path.length - { if (entity.isInstanceOf[Package]) 0 else 1 })
-
- val entityWithExtras = entity.asJava(Map(
- "assets" -> s"${toRoot}docassets",
- "index" -> s"${toRoot}docassets/index.js",
- "currentEntity" -> entity.json
- ))
-
- mf.compile(new InputStreamReader(inputStream), "template")
- .execute(writer, entityWithExtras)
-
- inputStream.close()
- writer.flush()
- writer.toString
- } catch {
- case fnf: FileNotFoundException =>
- dottydoc.println(s"""Couldn't find the template: "${template.getFile}"...exiting""")
- System.exit(1); ""
- }
-
- def writeFile(str: String, path: String, file: String): Unit =
- writeFile(str.map(_.toByte).toArray, path, file)
-
- def writeFile(bytes: Array[Byte], path: String, file: String): Unit = {
- def printToFile(f: JFile)(op: JPrintWriter => Unit) = {
- val bos = new BufferedOutputStream(new FileOutputStream(f))
- try {
- Stream.continually(bos.write(bytes))
- } finally bos.close()
- }
-
- new JFile(path).mkdirs()
- printToFile(new JFile(path + file))(printer => bytes.foreach(printer.print))
- }
-
- def copy(src: InputStream, path: String, name: String): Unit = {
- val reader = new BufferedInputStream(src)
- try {
- val bytes = Stream.continually(reader.read).takeWhile(-1 != _).map(_.toByte)
- writeFile(bytes.toArray, path + "/docassets/", name)
- src.close()
- } finally reader.close()
- }
-}
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/mutate.scala b/doc-tool/src/dotty/tools/dottydoc/util/mutate.scala
index a5a4dfec6..4633bf257 100644
--- a/doc-tool/src/dotty/tools/dottydoc/util/mutate.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/util/mutate.scala
@@ -16,9 +16,13 @@ object setters {
case x: ObjectImpl => x.comment = to
case x: DefImpl => x.comment = to
case x: ValImpl => x.comment = to
+ case x: TypeAliasImpl => x.comment = to
}
def setParent(ent: Entity, to: Entity): Unit = ent match {
+ case e: PackageImpl =>
+ e.parent = to
+ e.members.foreach(setParent(_, e))
case e: ClassImpl =>
e.parent = to
e.members.foreach(setParent(_, e))
@@ -35,6 +39,8 @@ object setters {
e.parent = to
case e: DefImpl =>
e.parent = to
+ case e: TypeAliasImpl =>
+ e.parent = to
case _ => ()
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala
index dd3d21f8d..005545d67 100644
--- a/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/util/syntax.scala
@@ -6,6 +6,11 @@ import dotc.core.Contexts.Context
import dotc.core.Comments._
import model.Package
import core.ContextDottydoc
+import dotc.core.Symbols._
+
+import dotc.util.{ SourcePosition, SourceFile }
+import dotc.util.Positions.Position
+import scala.io.Codec
object syntax {
implicit class ContextWithContextDottydoc(val ctx: Context) extends AnyVal {
@@ -13,4 +18,10 @@ object syntax {
throw new IllegalStateException("DocBase must be set before running dottydoc phases")
}.asInstanceOf[ContextDottydoc]
}
+
+ implicit class SymbolExtensions(val sym: Symbol) extends AnyVal {
+ def sourcePosition(pos: Position)(implicit ctx: Context): SourcePosition =
+ new SourceFile(sym.sourceFile, Codec(ctx.settings.encoding.value)) atPos pos
+
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/Traversing.scala b/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
index a3b60fa44..9c2e3bf54 100644
--- a/doc-tool/src/dotty/tools/dottydoc/util/Traversing.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
@@ -22,4 +22,22 @@ object traversing {
"../" * (from.path.length - offset) +
to.path.mkString("", "/", ".html")
}
+
+
+ def rootPackages(pkgs: Map[String, Package]): List[String] = {
+ var currentDepth = Int.MaxValue
+ var packs = List.empty[String]
+
+ for (key <- pkgs.keys) {
+ val keyDepth = key.split("\\.").length
+ packs =
+ if (keyDepth < currentDepth) {
+ currentDepth = keyDepth
+ key :: Nil
+ } else if (keyDepth == currentDepth) {
+ key :: packs
+ } else packs
+ }
+ packs
+ }
}
diff --git a/doc-tool/test/CommentCleanerTest.scala b/doc-tool/test/CommentCleanerTest.scala
new file mode 100644
index 000000000..5cf5614c4
--- /dev/null
+++ b/doc-tool/test/CommentCleanerTest.scala
@@ -0,0 +1,83 @@
+package dotty.tools
+package dottydoc
+
+import org.junit.Test
+import org.junit.Assert._
+
+import model.comment.CommentCleaner
+
+class CommentCleanerTest extends CommentCleaner {
+ @Test def simpleOneliner = {
+ assertEquals(List("lol"), clean("/** lol */"))
+ }
+
+ @Test def multiline = {
+ val docstring = clean {
+ """|/** First
+ | * Second
+ | */
+ |""".stripMargin
+ }
+
+ assertEquals(List("First", "Second", ""), docstring)
+ }
+
+ @Test def multilineBad = {
+ val docstring = clean {
+ """|/** First
+ | * Second
+ | */
+ |""".stripMargin
+ }
+
+ assertEquals(List("First", " Second", ""), docstring)
+ }
+
+ @Test def multilineWorse = {
+ val docstring = clean {
+ """|/** First
+ | * Second
+ | * Third
+ | */
+ |""".stripMargin
+ }
+
+ assertEquals(List("First", " Second", "Third", ""), docstring)
+ }
+
+ @Test def multilineFirstNoSpace = {
+ val docstring = clean {
+ """|/**First
+ | * Second
+ | * Third
+ | */
+ |""".stripMargin
+ }
+
+ assertEquals(List("First", " Second", "Third", ""), docstring)
+ }
+
+ @Test def multilineFirstTwoSpaces = {
+ val docstring = clean {
+ """|/** First
+ | * Second
+ | * Third
+ | */
+ |""".stripMargin
+ }
+
+ assertEquals(List("First", " Second", "Third", ""), docstring)
+ }
+
+ @Test def multilineFirstThreeSpaces = {
+ val docstring = clean {
+ """|/** First
+ | * Second
+ | * Third
+ | */
+ |""".stripMargin
+ }
+
+ assertEquals(List(" First", " Second", "Third", ""), docstring)
+ }
+}
diff --git a/doc-tool/test/ConstructorTest.scala b/doc-tool/test/ConstructorTest.scala
index 44a05acad..b61c5911d 100644
--- a/doc-tool/test/ConstructorTest.scala
+++ b/doc-tool/test/ConstructorTest.scala
@@ -9,7 +9,7 @@ import model._
import model.internal._
import model.references._
-class Constructors extends DottyTest {
+class Constructors extends DottyDocTest {
@Test def singleClassConstructor = {
val source = new SourceFile (
"Class.scala",
@@ -22,7 +22,7 @@ class Constructors extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(cls: Class), _, _) =>
+ case PackageImpl(_, _, _, List(cls: Class), _, _, _, _) =>
cls.constructors.headOption match {
case Some(ParamListImpl(NamedReference("str", _, false, false) :: Nil, false) :: Nil) =>
// success!
@@ -44,7 +44,7 @@ class Constructors extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(cls: Class), _, _) =>
+ case PackageImpl(_, _, _, List(cls: Class), _, _, _, _) =>
cls.constructors match {
case (
ParamListImpl(NamedReference("str1", _, false, false) :: Nil, false) ::
@@ -69,7 +69,7 @@ class Constructors extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(cls: Class), _, _) =>
+ case PackageImpl(_, _, _, List(cls: Class), _, _, _, _) =>
cls.constructors match {
case (
ParamListImpl(NamedReference("str1", _, false, false) :: Nil, false) ::
@@ -101,7 +101,7 @@ class Constructors extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(cls: Class), _, _) =>
+ case PackageImpl(_, _, _, List(cls: Class), _, _, _, _) =>
cls.constructors match {
case (
ParamListImpl(NamedReference("main", _, false, false) :: Nil, false) :: Nil
@@ -139,7 +139,7 @@ class Constructors extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(cls: CaseClass, obj: Object), _, _) =>
+ case PackageImpl(_, _, _, List(cls: CaseClass, obj: Object), _, _, _, _) =>
cls.constructors match {
case (
ParamListImpl(NamedReference("main", _, false, false) :: Nil, false) :: Nil
@@ -172,7 +172,7 @@ class Constructors extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(trt: Trait), _, _) =>
+ case PackageImpl(_, _, _, List(trt: Trait), _, _, _, _) =>
trt.traitParams match {
case ParamListImpl(NamedReference("main", _, false, false) :: Nil, false) :: Nil =>
case _ =>
@@ -184,28 +184,4 @@ class Constructors extends DottyTest {
}
}
}
-
- @Test def testJson = {
- val actualSource =
- """
- |package scala
- |
- |trait Trait(val main: String)
- |class Class(val main: String)
- |case class CaseClass(main: String)
- """.stripMargin
-
- val source = new SourceFile ("JsonTest.scala", actualSource)
-
- checkSources(source :: Nil) { packages =>
- packages("scala") match {
- case PackageImpl(_, _, List(cc: CaseClass, _, cls: Class, trt: Trait), _, _) =>
- import model.json._
- lazy val incorrectJson = s"The json generated for:\n$actualSource\n\nIs not correct"
- assert(cc.json.contains(s""""constructors":[[{"list":[{"title":"main""""), incorrectJson)
- assert(cls.json.contains(s""""constructors":[[{"list":[{"title":"main""""), incorrectJson)
- assert(trt.json.contains(s""""traitParams":[{"list":[{"title":"main""""), incorrectJson)
- }
- }
- }
}
diff --git a/doc-tool/test/BaseTest.scala b/doc-tool/test/DottyDocTest.scala
index 835911ca5..4202dca73 100644
--- a/doc-tool/test/BaseTest.scala
+++ b/doc-tool/test/DottyDocTest.scala
@@ -10,7 +10,7 @@ import dottydoc.core.{ DocASTPhase, ContextDottydoc }
import model.Package
import dotty.tools.dottydoc.util.syntax._
-trait DottyTest {
+trait DottyDocTest {
dotty.tools.dotc.parsing.Scanners // initialize keywords
implicit val ctx: FreshContext = {
@@ -20,10 +20,11 @@ trait DottyTest {
ctx.setSetting(ctx.settings.language, List("Scala2"))
ctx.setSetting(ctx.settings.YkeepComments, true)
ctx.setSetting(ctx.settings.YnoInline, true)
+ ctx.setSetting(ctx.settings.wikiSyntax, true)
ctx.setProperty(ContextDoc, new ContextDottydoc)
ctx.setSetting(
ctx.settings.classpath,
- "../library/target/scala-2.11/dotty-library_2.11-0.1.1-SNAPSHOT.jar"
+ dotty.Jars.dottyLib
)
base.initialize()(ctx)
ctx
diff --git a/doc-tool/test/GenDocs.scala b/doc-tool/test/GenDocs.scala
new file mode 100644
index 000000000..942347975
--- /dev/null
+++ b/doc-tool/test/GenDocs.scala
@@ -0,0 +1,46 @@
+package dotty.tools
+package dottydoc
+
+object Files {
+ type JFile = java.io.File
+
+ implicit class ToUrl(val f: JFile) extends AnyVal {
+ def getUrl = f.toURI.toURL
+ }
+}
+
+trait LocalResources extends DocDriver {
+ import Files._
+ import dotty.Jars
+
+ def getFiles(file: JFile): Array[JFile] =
+ if (file.isDirectory) file.listFiles.flatMap(getFiles)
+ else if (file.getAbsolutePath.endsWith(".scala")) Array(file)
+ else Array()
+
+ def withClasspath(files: Array[String]) =
+ "-siteroot" +: "../docs" +:
+ "-project" +: "Dotty" +:
+ "-language:Scala2" +:
+ "-classpath" +:
+ (Jars.dottyLib + ":" + Jars.dottyInterfaces) +:
+ files
+}
+
+object GenCollections extends LocalResources {
+ import Files._
+
+ val collections = TestWhitelistedCollections.files
+
+ override def main(args: Array[String]): Unit =
+ super.main(withClasspath(collections.toArray))
+}
+
+object GenDottyDocs extends LocalResources {
+ import Files._
+
+ val dottyFiles = new JFile("../compiler/src/dotty").listFiles.flatMap(getFiles).map(_.getAbsolutePath)
+
+ override def main(args: Array[String]): Unit =
+ super.main(withClasspath(dottyFiles))
+}
diff --git a/doc-tool/test/MarkdownTests.scala b/doc-tool/test/MarkdownTests.scala
new file mode 100644
index 000000000..6ac7a3a4e
--- /dev/null
+++ b/doc-tool/test/MarkdownTests.scala
@@ -0,0 +1,309 @@
+package dotty.tools
+package dottydoc
+
+import org.junit.Test
+import org.junit.Assert._
+
+import dotc.core.Contexts.{ Context, ContextBase, FreshContext }
+import dotc.core.Comments.{ ContextDoc, ContextDocstrings }
+import dottydoc.core.ContextDottydoc
+
+class MarkdownTests extends DottyDocTest {
+ override implicit val ctx: FreshContext = {
+ // TODO: check if can reuse parent instead of copy-paste
+ val base = new ContextBase
+ import base.settings._
+ val ctx = base.initialCtx.fresh
+ ctx.setSetting(ctx.settings.language, List("Scala2"))
+ ctx.setSetting(ctx.settings.YkeepComments, true)
+ ctx.setSetting(ctx.settings.YnoInline, true)
+ // No wiki syntax!
+ ctx.setSetting(ctx.settings.wikiSyntax, false)
+ ctx.setProperty(ContextDoc, new ContextDottydoc)
+ ctx.setSetting(
+ ctx.settings.classpath,
+ dotty.Jars.dottyLib
+ )
+ base.initialize()(ctx)
+ ctx
+ }
+
+ @Test def simpleMarkdown = {
+ val source =
+ """
+ |package scala
+ |
+ |/** *Hello*, world! */
+ |trait HelloWorld
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals("<p><em>Hello</em>, world!</p>", traitCmt)
+ }
+ }
+
+ @Test def outerLink = {
+ val source =
+ """
+ |package scala
+ |
+ |/** [out](http://www.google.com) */
+ |trait HelloWorld
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals("""<p><a href="http://www.google.com">out</a></p>""", traitCmt)
+ }
+ }
+
+ @Test def relativeLink = {
+ val source =
+ """
+ |package scala
+ |
+ |/** [None](./None.html) */
+ |trait HelloWorld
+ |
+ |trait None
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals("""<p><a href="./None.html">None</a></p>""", traitCmt)
+ }
+ }
+
+ @Test def absoluteLink = {
+ val source =
+ """
+ |package scala
+ |
+ |/** [None](scala.None) */
+ |trait HelloWorld
+ |
+ |trait None
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals("""<p><a href="../scala/None.html">None</a></p>""", traitCmt)
+ }
+ }
+
+ @Test def handleLists = {
+ val source =
+ """
+ |package scala
+ |
+ |/** - Item1
+ | * - Item2
+ | * - Item3
+ | */
+ |trait HelloWorld
+ |
+ |trait None
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals(
+ """|<ul>
+ |<li>Item1</li>
+ |<li>Item2</li>
+ |<li>Item3</li>
+ |</ul>""".stripMargin, traitCmt)
+ }
+ }
+
+ @Test def handleNestedLists = {
+ val source =
+ """
+ |package scala
+ |
+ |/** - Item1
+ | * - Item1a
+ | * - Item1b
+ | * - Item2
+ | * - Item3
+ | */
+ |trait HelloWorld
+ |
+ |trait None
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals(
+ """|<ul>
+ |<li>Item1
+ |<ul>
+ |<li>Item1a</li>
+ |<li>Item1b</li>
+ |</ul>
+ |</li>
+ |<li>Item2</li>
+ |<li>Item3</li>
+ |</ul>""".stripMargin, traitCmt)
+ }
+ }
+
+ @Test def handleCodeBlock = {
+ val source =
+ """
+ |package scala
+ |
+ |/** ```scala
+ | * val x = 1 + 5
+ | * ```
+ | */
+ |trait HelloWorld
+ |
+ |trait None
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals(
+ """|<pre><code class="language-scala">val x = 1 + 5
+ |</code></pre>""".stripMargin, traitCmt)
+ }
+ }
+
+ @Test def handleCodeBlockJavaDocstring = {
+ // the following works, but not when the start of the codeblock is on the
+ // first line
+ val source =
+ """
+ |package scala
+ |
+ |/**
+ | * ```scala
+ | * val x = 1 + 5
+ | * ```
+ | */
+ |trait HelloWorld
+ |
+ |trait None
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.body))
+ .get
+ .trim
+
+ assertEquals(
+ """|<pre><code class="language-scala">val x = 1 + 5
+ |</code></pre>""".stripMargin, traitCmt)
+ }
+ }
+
+ @Test def docstringSummary = {
+ val source =
+ """
+ |package scala
+ |
+ |/** This
+ | * ====
+ | * is a short text [that](http://google.com) should not be more than a
+ | * `few` lines long. This text *should* be shortened somewhere that is
+ | * appropriate for the **ui**. Might be here, or there or somewhere
+ | * else.
+ | */
+ |trait HelloWorld
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.short))
+ .get
+ .trim
+
+ assert(
+ traitCmt.endsWith("Might be here...\n</p>"),
+ s"""|docstring summary should strip the following docstring so that it ends in "Might be here..."
+ |
+ |$traitCmt""".stripMargin
+ )
+ }
+ }
+
+ @Test def docstringSummaryWithImage = {
+ val source =
+ """
+ |package scala
+ |
+ |/** This
+ | * ====
+ | * should quit before ![alt text](https://whatever.com/1.png "Img Text"),
+ | * I shouldn't be visible.
+ | */
+ |trait HelloWorld
+ """.stripMargin
+
+ checkSource(source) { packages =>
+ val traitCmt =
+ packages("scala")
+ .children.find(_.path.mkString(".") == "scala.HelloWorld")
+ .flatMap(_.comment.map(_.short))
+ .get
+ .trim
+
+ assert(
+ !traitCmt.contains("<img") &&
+ !traitCmt.contains("I shouldn't be visible."),
+ s"""|docstring summary shouldn't contain image, error in `MarkdownShortener.scala`
+ |
+ |$traitCmt""".stripMargin)
+ }
+
+ }
+}
diff --git a/doc-tool/test/PackageStructure.scala b/doc-tool/test/PackageStructure.scala
index 4e7006bfe..569bfbc1c 100644
--- a/doc-tool/test/PackageStructure.scala
+++ b/doc-tool/test/PackageStructure.scala
@@ -7,7 +7,7 @@ import org.junit.Assert._
import dotc.util.SourceFile
import model.internal._
-class PackageStructure extends DottyTest {
+class PackageStructure extends DottyDocTest {
@Test def multipleCompilationUnits = {
val source1 = new SourceFile(
"TraitA.scala",
@@ -29,7 +29,7 @@ class PackageStructure extends DottyTest {
checkSources(source1 :: source2 :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(tA, tB), _, _) =>
+ case PackageImpl(_, _, _, List(tA, tB), _, _, _, _) =>
assert(
tA.name == "A" && tB.name == "B",
s"trait A had name '${tA.name}' and trait B had name '${tB.name}'"
@@ -63,9 +63,10 @@ class PackageStructure extends DottyTest {
packages("scala") match {
case PackageImpl(
_,
+ _,
"scala",
- List(PackageImpl(_, "scala.collection", List(tA, tB), _, _)),
- _, _
+ List(PackageImpl(_, _, "scala.collection", List(tA, tB), _, _, _, _)),
+ _, _, _, _
) =>
assert(
tA.name == "A" && tB.name == "B",
@@ -77,7 +78,7 @@ class PackageStructure extends DottyTest {
}
packages("scala.collection") match {
- case PackageImpl(_, "scala.collection", List(tA, tB), _, _) =>
+ 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}'"
diff --git a/doc-tool/test/SimpleComments.scala b/doc-tool/test/SimpleComments.scala
index 959eb1745..bc420feeb 100644
--- a/doc-tool/test/SimpleComments.scala
+++ b/doc-tool/test/SimpleComments.scala
@@ -4,7 +4,7 @@ package dottydoc
import org.junit.Test
import org.junit.Assert._
-class TestSimpleComments extends DottyTest {
+class TestSimpleComments extends DottyDocTest {
@Test def simpleComment = {
val source =
@@ -25,5 +25,4 @@ class TestSimpleComments extends DottyTest {
assertEquals(traitCmt, "<p>Hello, world!</p>")
}
}
-
}
diff --git a/doc-tool/test/SourceFileOps.scala b/doc-tool/test/SourceFileOps.scala
new file mode 100644
index 000000000..37520921d
--- /dev/null
+++ b/doc-tool/test/SourceFileOps.scala
@@ -0,0 +1,51 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import dotc.util.SourceFile
+import java.io.{ BufferedWriter, OutputStreamWriter }
+import io.VirtualFile
+import scala.io.Codec
+
+import model.Package
+
+trait SourceFileOps {
+ import scala.collection.JavaConverters._
+ val site = new Site(new java.io.File("../doc-tool/resources/"), "test-site", Map.empty)
+
+ def stringToSource(path: String, sourceCode: String): SourceFile = {
+ val virtualFile = new VirtualFile(path, path)
+ val writer = new BufferedWriter(new OutputStreamWriter(virtualFile.output, "UTF-8"))
+ writer.write(sourceCode)
+ writer.close()
+
+ new SourceFile(virtualFile, Codec.UTF8)
+ }
+
+ def markdownPage(
+ sourceCode: String,
+ path: String = "test-page",
+ params: Map[String, AnyRef] = Map.empty,
+ includes: Map[String, Include] = Map.empty,
+ docs: Map[String, Package] = Map.empty
+ ) = new MarkdownPage(
+ path,
+ stringToSource(path, sourceCode),
+ params,
+ includes,
+ docs
+ )
+
+ def htmlPage(
+ sourceCode: String,
+ path: String = "test-page",
+ params: Map[String, AnyRef] = Map.empty,
+ includes: Map[String, Include] = Map.empty,
+ docs: Map[String, Package] = Map.empty
+ ) = new HtmlPage(
+ path,
+ stringToSource(path, sourceCode),
+ params,
+ includes
+ )
+}
diff --git a/doc-tool/test/TemplateErrorTests.scala b/doc-tool/test/TemplateErrorTests.scala
new file mode 100644
index 000000000..3359c7791
--- /dev/null
+++ b/doc-tool/test/TemplateErrorTests.scala
@@ -0,0 +1,32 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import org.junit.Test
+import org.junit.Assert._
+
+class TemplateErrorTests extends DottyDocTest with SourceFileOps {
+ @Test def unclosedTag: Unit = {
+ htmlPage(
+ """|Yo dawg:
+ |{% include "stuff"
+ |I heard you like to include stuff""".stripMargin
+ ).html
+ }
+
+ @Test def missingEndif: Unit = {
+ htmlPage(
+ """|{% if someStuff %}
+ |Dude
+ |""".stripMargin
+ ).html
+ }
+
+ @Test def nonExistingTag: Unit = {
+ htmlPage(
+ """|{% someStuff 'ofDude' %}
+ |Dude
+ |""".stripMargin
+ ).html
+ }
+}
diff --git a/doc-tool/test/UsecaseTest.scala b/doc-tool/test/UsecaseTest.scala
index 113d54aad..4eb072b98 100644
--- a/doc-tool/test/UsecaseTest.scala
+++ b/doc-tool/test/UsecaseTest.scala
@@ -10,7 +10,7 @@ import model.internal._
import model.references._
import util.syntax._
-class UsecaseTest extends DottyTest {
+class UsecaseTest extends DottyDocTest {
@Test def simpleUsecase = {
val source = new SourceFile(
"DefWithUseCase.scala",
@@ -29,7 +29,7 @@ class UsecaseTest extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(trt: Trait), _, _) =>
+ case PackageImpl(_, _, _, List(trt: Trait), _, _, _, _) =>
val List(foo: Def) = trt.members
assert(foo.comment.isDefined, "Lost comment in transformations")
@@ -73,7 +73,7 @@ class UsecaseTest extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(trt: Trait), _, _) =>
+ case PackageImpl(_, _, _, List(trt: Trait), _, _, _, _) =>
val List(foo: Def) = trt.members
val returnValue = foo.returnValue match {
@@ -118,7 +118,7 @@ class UsecaseTest extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(trt: Trait), _, _) =>
+ case PackageImpl(_, _, _, List(trt: Trait), _, _, _, _) =>
val List(foo: Def) = trt.members
val returnValue = foo.returnValue match {
@@ -166,7 +166,7 @@ class UsecaseTest extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(trt: Trait), _, _) =>
+ case PackageImpl(_, _, _, List(trt: Trait), _, _, _, _) =>
val List(map: Def) = trt.members
val returnValue = map.returnValue match {
@@ -209,7 +209,7 @@ class UsecaseTest extends DottyTest {
checkSources(source :: Nil) { packages =>
packages("scala") match {
- case PackageImpl(_, _, List(trt: Trait), _, _) =>
+ case PackageImpl(_, _, _, List(trt: Trait), _, _, _, _) =>
val List(map: Def) = trt.members
assert(map.comment.isDefined, "Lost comment in transformations")
diff --git a/doc-tool/test/WhitelistedStdLib.scala b/doc-tool/test/WhitelistedStdLib.scala
index 90df859e0..9092d1ded 100644
--- a/doc-tool/test/WhitelistedStdLib.scala
+++ b/doc-tool/test/WhitelistedStdLib.scala
@@ -4,12 +4,10 @@ package dottydoc
import org.junit.Test
import org.junit.Assert._
-class WhitelistedStdLib extends DottyTest {
- val files: List[String] =
- StdLibSources.whitelisted.filterNot(_.endsWith("package.scala"))
+class TestWhitelistedCollections extends DottyDocTest {
@Test def arrayHasDocumentation =
- checkFiles(files) { packages =>
+ checkFiles(TestWhitelistedCollections.files) { packages =>
val array =
packages("scala")
.children.find(_.path.mkString(".") == "scala.Array")
@@ -19,7 +17,7 @@ class WhitelistedStdLib extends DottyTest {
}
@Test def traitImmutableHasDocumentation =
- checkFiles(files) { packages =>
+ checkFiles(TestWhitelistedCollections.files) { packages =>
val imm =
packages("scala")
.children.find(_.path.mkString(".") == "scala.Immutable")
@@ -33,3 +31,9 @@ class WhitelistedStdLib extends DottyTest {
"Imm did not have a comment with length > 0")
}
}
+
+object TestWhitelistedCollections {
+ val files: List[String] =
+ StdLibSources.whitelisted
+ .filterNot(_.endsWith("package.scala"))
+}
diff --git a/doc-tool/test/dotty/tools/dottydoc/staticsite/PageTests.scala b/doc-tool/test/dotty/tools/dottydoc/staticsite/PageTests.scala
new file mode 100644
index 000000000..7febe7fe5
--- /dev/null
+++ b/doc-tool/test/dotty/tools/dottydoc/staticsite/PageTests.scala
@@ -0,0 +1,102 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import org.junit.Test
+import org.junit.Assert._
+
+class PageTests extends DottyDocTest with SourceFileOps {
+ import scala.collection.JavaConverters._
+
+ @Test def mdHas1Key = {
+ val page = markdownPage(
+ """|---
+ |key:
+ |---
+ |
+ |great""".stripMargin
+ )
+
+ assert(
+ page.yaml == Map("key" -> List.empty.asJava),
+ s"""incorrect yaml, expected "key:" without key in: ${page.yaml}"""
+ )
+
+ assertEquals("<p>great</p>\n", page.html.get)
+ }
+
+ @Test def yamlPreservesLiquidTags = {
+ val page1 = markdownPage(
+ """|---
+ |key:
+ |---
+ |
+ |{{ content }}""".stripMargin,
+ params = Map("content" -> "Hello, world!")
+ )
+
+ assert(
+ page1.yaml == Map("key" -> List.empty.asJava),
+ s"""incorrect yaml, expected "key:" without key in: ${page1.yaml}"""
+ )
+
+ assertEquals("<p>Hello, world!</p>\n", page1.html.get)
+
+ val page2 = markdownPage(
+ """|{{ content }}""".stripMargin,
+ params = Map("content" -> "hello")
+ )
+ assert(
+ page2.yaml == Map(),
+ s"""incorrect yaml, expected "key:" without key in: ${page2.yaml}"""
+ )
+ assertEquals("<p>hello</p>\n", page2.html.get)
+
+ val page3 = markdownPage(
+ """|{% if product.title == "Awesome Shoes" %}
+ |These shoes are awesome!
+ |{% endif %}""".stripMargin,
+ params = Map("product" -> Map("title" -> "Awesome Shoes").asJava)
+ )
+
+ assertEquals(
+ "<p>These shoes are awesome!</p>\n",
+ page3.html.get
+ )
+ }
+
+ @Test def simpleHtmlPage = {
+ val p1 = htmlPage("""<h1>{{ "hello, world!" }}</h1>""")
+ assert(p1.yaml == Map(), "non-empty yaml found")
+ assertEquals("<h1>hello, world!</h1>", p1.html.get)
+ }
+
+ @Test def htmlPageHasNoYaml = {
+ val page = htmlPage(
+ """|---
+ |layout: main
+ |---
+ |
+ |Hello, world!""".stripMargin
+ )
+
+ assert(!page.html.get.contains("---\nlayout: main\n---"),
+ s"page still contains yaml:\n${page.html.get}")
+ }
+
+ @Test def illegalYamlFrontMatter = try {
+ val page = htmlPage(
+ """|---
+ |layout: main
+ |
+ |
+ |Hello, world!""".stripMargin
+ )
+
+ page.html.get
+ fail("illegal front matter didn't throw exception")
+ } catch {
+ case IllegalFrontMatter(x) => // success!
+ case t: Throwable => throw t
+ }
+}
diff --git a/doc-tool/test/dotty/tools/dottydoc/staticsite/SiteTests.scala b/doc-tool/test/dotty/tools/dottydoc/staticsite/SiteTests.scala
new file mode 100644
index 000000000..a4279e18c
--- /dev/null
+++ b/doc-tool/test/dotty/tools/dottydoc/staticsite/SiteTests.scala
@@ -0,0 +1,100 @@
+package dotty.tools
+package dottydoc
+package staticsite
+
+import org.junit.Test
+import org.junit.Assert._
+
+class SiteTests extends DottyDocTest with SourceFileOps {
+ @Test def hasCorrectLayoutFiles = {
+ assert(site.root.exists && site.root.isDirectory,
+ s"'${site.root.getName}' is not a directory")
+
+ val expectedLayouts = Set("main", "index", "sidebar", "blog-page", "doc-page", "api-page")
+ assert(site.layouts.keys == expectedLayouts,
+ s"Incorrect layouts in: ${site.layouts.keys}, expected: $expectedLayouts")
+ }
+
+ @Test def renderHelloInMainLayout = {
+ val renderedPage = site.render(htmlPage(
+ """|---
+ |layout: main
+ |---
+ |
+ |Hello, world!""".stripMargin
+ ), Map.empty).get
+
+ assert(
+ renderedPage.contains("Hello, world!") &&
+ !renderedPage.contains("---\nlayout: main\n---\n") &&
+ renderedPage.contains("<!DOCTYPE html>"),
+ "html page did not render properly"
+ )
+ }
+
+ @Test def renderMultipleTemplates = {
+ val renderedPage = site.render(htmlPage(
+ """|---
+ |layout: index
+ |---
+ |Hello, world!""".stripMargin
+ ), Map.empty).get
+
+ assert(
+ renderedPage.contains("<h1>Hello, world!</h1>") &&
+ !renderedPage.contains("---\nlayout: main\n---\n") &&
+ !renderedPage.contains("---\nlayout: index\n---\n") &&
+ renderedPage.contains("<!DOCTYPE html>"),
+ "html page did not render properly"
+ )
+ }
+
+ @Test def preservesPageYaml = {
+ val renderedPage = site.render(htmlPage(
+ """|---
+ |title: Hello, world
+ |layout: index
+ |---
+ |Hello, world!""".stripMargin
+ ), Map.empty).get
+
+ assert(
+ renderedPage.contains("<h1>Hello, world!</h1>") &&
+ !renderedPage.contains("---\nlayout: main\n---\n") &&
+ !renderedPage.contains("---\nlayout: index\n---\n") &&
+ renderedPage.contains("<title>Hello, world</title>") &&
+ renderedPage.contains("<!DOCTYPE html>"),
+ "html page did not render properly:\n" + renderedPage
+ )
+ }
+
+ @Test def include = {
+ val renderedInclude = site.render(
+ htmlPage("""{% include "header.html" %}""", includes = site.includes),
+ Map.empty
+ ).get
+
+ assertEquals("<h1>Some header</h1>\n", renderedInclude)
+ }
+
+ @Test def siteStructure = {
+ val assets = site.staticAssets.map(site.stripRoot).toSet
+ val compd = site.compilableFiles.map(site.stripRoot).toSet
+
+ val expectedAssets = Set(
+ "css/api-page.css",
+ "css/dottydoc.css",
+ "css/color-brewer.css",
+ "js/highlight.pack.js"
+ )
+ val expectedCompd = Set(
+ // Directories starting in `_` are not included in compilable files
+ "index.md"
+ )
+
+ assert(expectedAssets == assets,
+ s"assets incorrect, found: $assets - expected $expectedAssets")
+ assert(expectedCompd == compd,
+ s"compilable files incorrect, found: $compd - expected $expectedCompd")
+ }
+}
diff --git a/docs/Gemfile b/docs/Gemfile
deleted file mode 100644
index 4f3c7d08f..000000000
--- a/docs/Gemfile
+++ /dev/null
@@ -1,27 +0,0 @@
-source "https://rubygems.org"
-ruby RUBY_VERSION
-
-# Hello! This is where you manage which Jekyll version is used to run.
-# When you want to use a different version, change it below, save the
-# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
-#
-# bundle exec jekyll serve
-#
-# This will help ensure the proper Jekyll version is running.
-# Happy Jekylling!
-gem "jekyll", "3.2.1"
-
-# This is the default theme for new Jekyll sites. You may change this to anything you like.
-gem "minima"
-
-# Table of contents
-gem 'jekyll-toc'
-
-# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
-# uncomment the line below. To upgrade, run `bundle update github-pages`.
-# gem "github-pages", group: :jekyll_plugins
-
-# If you have any plugins, put them here!
-# group :jekyll_plugins do
-# gem "jekyll-github-metadata", "~> 1.0"
-# end
diff --git a/docs/_config.yml b/docs/_config.yml
deleted file mode 100644
index 1bdfb808a..000000000
--- a/docs/_config.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-title: Dotty Documentation
-repository_url: "http://github.com/lampepfl/dotty"
-baseurl: ""
-theme: minima
-gems:
- - jekyll-toc
diff --git a/docs/_includes/faq.html b/docs/_includes/faq.html
index 7c2126ac4..569162d57 100644
--- a/docs/_includes/faq.html
+++ b/docs/_includes/faq.html
@@ -86,6 +86,14 @@
Nicolas Stucki
</div>
</div>
+ <div class="contributors-cell">
+ <div class="contributor">
+ <a href="http://github.com/OlivierBlanvillain">
+ <img src="{{ site.baseurl }}/images/olivier.jpeg">
+ </a>
+ Olivier Blanvillain
+ </div>
+ </div>
</div>
<div class="centered-text">
diff --git a/docs/_includes/features.html b/docs/_includes/features.html
index ba004d68b..0f8d4eab2 100644
--- a/docs/_includes/features.html
+++ b/docs/_includes/features.html
@@ -69,12 +69,12 @@
<td>In progress</td>
</tr>
<tr class="even">
- <td></td>
- <td></td>
+ <td>HList &amp; HMaps/Record types</td>
+ <td>In progress</td>
</tr>
<tr class="odd">
- <td>HList &amp; HMaps/Record types</td>
- <td>Considered</td>
+ <td></td>
+ <td></td>
</tr>
<tr class="even">
<td>Implicit functions</td>
diff --git a/docs/_includes/getting-started.html b/docs/_includes/getting-started.html
index fc99788f9..00b7c869c 100644
--- a/docs/_includes/getting-started.html
+++ b/docs/_includes/getting-started.html
@@ -19,7 +19,7 @@ enablePlugins(DottyPlugin)</code></pre>
<h2 id="build.properties">build.properties</h2>
<pre class="sourceCode bordered"><code>sbt.version=0.13.11</code></pre>
<h2 id="plugins.sbt">plugins.sbt</h2>
- <pre class="sourceCode bordered"><code>addSbtPlugin("com.felixmulder" % "sbt-dotty" % "0.1.4")</code></pre>
+ <pre class="sourceCode bordered"><code>addSbtPlugin("com.felixmulder" % "sbt-dotty" % "0.1.7")</code></pre>
<p>
This plugin is based on the
<a href="https://github.com/smarter/dotty-example-project">
diff --git a/docs/_includes/logo-page.html b/docs/_includes/logo-page.html
index 53c466cf5..3131b6626 100644
--- a/docs/_includes/logo-page.html
+++ b/docs/_includes/logo-page.html
@@ -7,12 +7,12 @@
</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="{{ site.baseurl }}/blog">
+ <a class="nav-link" href="{{ site.baseurl }}/blog/index.html">
Blog
</a>
</li>
<li class="nav-item">
- <a class="nav-link" href="{{ site.baseurl }}/docs">
+ <a class="nav-link" href="{{ site.baseurl }}/docs/index.html">
Docs
</a>
</li>
diff --git a/docs/_includes/scala-logo.html b/docs/_includes/scala-logo.html
deleted file mode 100644
index bfabf88f7..000000000
--- a/docs/_includes/scala-logo.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<svg width="64" height="110" xmlns="http://www.w3.org/2000/svg">
- <g>
- <title>background</title>
- <rect x="-1" y="-1" width="9.664668" height="15.173648" id="canvas_background" fill="none"/>
- </g>
-
- <g>
- <title>Layer 1</title>
- <g id="logo">
- <g opacity="0.61" id="svg_1">
- <path fill="#FFFFFF" d="m0.5,41.9c0,0 62.9,6.3 62.9,16.8l0,-25.2c0,0 0,-10.5 -62.9,-16.8l0,9.8l0,15.4z" id="svg_2"/>
- <path fill="#FFFFFF" d="m0.5,75.5c0,0 62.9,6.3 62.9,16.8l0,-25.2c0,0 0,-10.5 -62.9,-16.8l0,25.2z" id="svg_3"/>
- </g>
- <path fill="#FFFFFF" d="m63.5,0l0,25.2c0,0 0,10.5 -62.9,16.8l0,-25.3c-0.1,0 62.9,-6.2 62.9,-16.7" id="svg_4"/>
- <path fill="#FFFFFF" d="m0.5,50.3c0,0 62.9,-6.3 62.9,-16.8l0,25.2c0,0 0,10.5 -62.9,16.8l0,-25.2z" id="svg_5"/>
- <path fill="#FFFFFF" d="m0.5,109l0,-25.2c0,0 62.9,-6.3 62.9,-16.8l0,25.2c0.1,0.1 0.1,10.5 -62.9,16.8" id="svg_6"/>
- </g>
- </g>
-</svg>
diff --git a/docs/_includes/toc.html b/docs/_includes/toc.html
deleted file mode 100644
index 45cbb5940..000000000
--- a/docs/_includes/toc.html
+++ /dev/null
@@ -1,43 +0,0 @@
-<div>
- <a href="{{ site.baseurl }}/">
- <div id="scala-logo">
- {% include scala-logo.html %}
- </div>
- </a>
- <form id="search-form" action="/search.html" method="get">
- <input placeholder="Search" type="text" id="search-box" name="query">
- </form>
- <ul id="categories">
- <li><ul><li><a href="{{ site.baseurl }}/blog">Blog</a></li></ul></li>
- <li><ul><li><a href="{{ site.baseurl }}/docs">Dotty Docs</a></li></ul></li>
- <li>
- Usage
- <ul>
- <li><a href="{{ site.baseurl }}/docs/usage/migrating.html">Migrating from Scala 2</a></li>
- <li><a href="{{ site.baseurl }}/docs/usage/sbt-projects.html">Using Dotty with sbt</a></li>
- <li><a href="{{ site.baseurl }}/docs/usage/cbt-projects.html">Using Dotty with cbt</a></li>
- </ul>
- </li>
- <li>
- Contributing
- <ul>
- <li><a href="{{ site.baseurl }}/docs/contributing/getting-started.html">Getting Started</a></li>
- <li><a href="{{ site.baseurl }}/docs/contributing/workflow.html">Workflow</a></li>
- <li><a href="{{ site.baseurl }}/docs/contributing/eclipse.html">Eclipse</a></li>
- <li><a href="{{ site.baseurl }}/docs/contributing/intellij-idea.html">Intellij-IDEA</a></li>
- </ul>
- </li>
- <li>
- Internals
- <ul>
- <li><a href="{{ site.baseurl }}/docs/internals/backend.html">Backend</a></li>
- <li><a href="{{ site.baseurl }}/docs/internals/contexts.html">Contexts</a></li>
- <li><a href="{{ site.baseurl }}/docs/internals/higher-kinded-v2.html">Higher Kinded Type Scheme</a></li>
- <li><a href="{{ site.baseurl }}/docs/internals/overall-structure.html">Project Structure</a></li>
- <li><a href="{{ site.baseurl }}/docs/internals/periods.html">Periods</a></li>
- <li><a href="{{ site.baseurl }}/docs/internals/type-system.html">Type System</a></li>
- <li><a href="{{ site.baseurl }}/docs/internals/dotc-scalac.html">Dotty vs Scala2</a></li>
- </ul>
- </li>
- </ul>
-</div>
diff --git a/docs/_layouts/blog.html b/docs/_layouts/blog.html
deleted file mode 100644
index f476bf5fa..000000000
--- a/docs/_layouts/blog.html
+++ /dev/null
@@ -1,17 +0,0 @@
----
-layout: default
----
-
-<h2 class="subtitle">{{ page.subTitle }}</h2>
-
-<div class="author-container {% if page.authorImg != null %} spaced {% endif %}">
- {% if page.authorImg != null %}
- <img src="{{ site.baseurl }}{{ page.authorImg }}"/>
- {% endif %}
- <div class="author-info">
- <div>{{ page.author }}</div>
- <div>{{ page.date | date: '%B %d, %Y' }}</div>
- </div>
-</div>
-
-{{ content }}
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html
deleted file mode 100644
index 6fa1a1d78..000000000
--- a/docs/_layouts/default.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<html>
- <head>
- <meta charset="utf-8">
-
- <title>Dotty - {{ page.title }}</title>
- <link rel="shortcut icon" type="image/png" href="{{ site.baseurl}}/images/favicon.png"/>
- <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/github.min.css">
- <link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
- </head>
- <body>
- <div id="container">
- <a class="logo-container" href="{{ site.baseurl }}/">
- <div id="scala-logo-mobile">
- {% include scala-logo.html %}
- </div>
- </a>
- <div id="content">
- <h1>{{ page.title }}</h1>
- <div class="edit-docs">
- <a href="{{site.repository_url}}/edit/master/docs/{{page.path}}">[edit on github]</a>
- </div>
- {{ content }}
- </div>
- <div id="toc">
- {% include toc.html %}
- </div>
- </div>
- </body>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.4.0/mark.min.js"></script>
- <script src="{{ site.baseurl }}/js/highlight.pack.js"></script>
- <script language="javascript">
- hljs.initHighlightingOnLoad();
- var x = document.links.length;
- for (i = 0; i < x; i++) {
- var thisHREF = document.links[i].href;
- if (thisHREF.indexOf(window.location.hostname) > -1) thisHREF = thisHREF.replace(".md",".html")
- document.links[i].setAttribute('href', thisHREF);
- }
-
- function getQueryVariable(variable) {
- var query = window.location.search.substring(1);
- var vars = query.split('&');
-
- for (var i = 0; i < vars.length; i++) {
- var pair = vars[i].split('=');
-
- if (pair[0] === variable) {
- return decodeURIComponent(pair[1].replace(/\+/g, '%20'));
- }
- }
- }
-
-
- var highlight = getQueryVariable("highlight");
- if (highlight) {
- var context = document.querySelector("#content");
- var instance = new Mark(context);
- instance.mark(highlight);
- }
- </script>
-</html>
diff --git a/docs/_layouts/index.html b/docs/_layouts/index.html
deleted file mode 100644
index aeb2fa7d7..000000000
--- a/docs/_layouts/index.html
+++ /dev/null
@@ -1,38 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="theme-color" content="#de332e">
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
- <meta http-equiv="x-ua-compatible" content="ie=edge">
- <meta property="og:image" content="http://dotty.epfl.ch/images/preview.png" />
-
- <title>Dotty</title>
-
- <link rel="icon" type="image/png" href="{{ site.baseurl }}/images/favicon.png">
- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" integrity="sha384-y3tfxAZXuh4HwSYylfB+J125MxIs6mR5FOHamPBG064zB+AFeWH94NdvaCBm8qnd" crossorigin="anonymous">
- <link rel="stylesheet" type="text/css" href="{{ site.baseurl }}/css/animate.css" />
- <link rel="stylesheet" type="text/css" href="{{ site.baseurl }}/css/default.css" />
-
- <!-- Yandex.Metrika counter -->
- <script type="text/javascript">
- (function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter37916575 = new Ya.Metrika({ id:37916575, clickmap:true, trackLinks:true, accurateTrackBounce:true, webvisor:true, trackHash:true }); } catch(e) { } }); var n = d.getElementsByTagName("script")[0], s = d.createElement("script"), f = function () { n.parentNode.insertBefore(s, n); }; s.type = "text/javascript"; s.async = true; s.src = "https://mc.yandex.ru/metrika/watch.js"; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })
- (document, window, "yandex_metrika_callbacks");
- </script>
- <noscript><div><img src="https://mc.yandex.ru/watch/37916575" style="position:absolute; left:-9999px;" alt /></div></noscript> <!-- /Yandex.Metrika counter -->
-
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" defer></script>
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/js/bootstrap.min.js" integrity="sha384-vZ2WRJMwsjRMW/8U7i6PWi6AlO1L79snBrmgiDpgIWJ82z8eA5lenwvxbMV1PAh7" crossorigin="anonymous" defer></script>
- <script src="https://cdn.jsdelivr.net/scrollreveal.js/3.1.4/scrollreveal.min.js" defer></script>
- <script src="{{ site.baseurl }}/js/index.js" defer></script>
- </head>
- <body>
- <div id="content">
- {% include logo-page.html %}
- {% include faq.html %}
- {% include features.html %}
- {% include getting-started.html %}
- </div>
- </body>
-</html>
diff --git a/docs/_layouts/search.html b/docs/_layouts/search.html
deleted file mode 100644
index 14994ab62..000000000
--- a/docs/_layouts/search.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<html>
- <head>
- <meta charset="utf-8">
-
- <title>Dotty - {{ page.title }}</title>
- <link rel="shortcut icon" type="image/png" href="{{ site.baseurl}}/images/favicon.png"/>
- <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/styles/github.min.css">
- <link rel="stylesheet" href="{{ site.baseurl }}/css/main.css">
- </head>
- <body>
- <div id="container">
- <div class="search">
- {{ content }}
- </div>
- </div>
- </body>
-</html>
diff --git a/docs/blog/_posts/2015-10-23-dotty-compiler-bootstraps.md b/docs/blog/_posts/2015-10-23-dotty-compiler-bootstraps.md
index b6ee44020..02f2825e2 100644
--- a/docs/blog/_posts/2015-10-23-dotty-compiler-bootstraps.md
+++ b/docs/blog/_posts/2015-10-23-dotty-compiler-bootstraps.md
@@ -3,6 +3,7 @@ layout: blog
author: Martin Odersky and Dmitry Petrashko
title: "We got liftoff!"
subTitle: The Dotty compiler for Scala bootstraps.
+excerpt_separator: <!--more-->
---
The [Dotty project](https://github.com/lampepfl/dotty)
@@ -16,6 +17,8 @@ Today we reached an important milestone: the Dotty compiler can
compile itself, and the compiled compiler can act as a drop-in for the
original one. This is what one calls a *bootstrap*.
+<!--more-->
+
## Why is this important?
The main reason is that this gives us a some validation of the
diff --git a/docs/blog/index.html b/docs/blog/index.html
index ac4b33c8a..b4725def7 100644
--- a/docs/blog/index.html
+++ b/docs/blog/index.html
@@ -1,5 +1,5 @@
---
-layout: default
+layout: blog-page
title: "Blog"
---
diff --git a/docs/css/default.css b/docs/css/default.css
index 6cd58a8b7..d01e81472 100644
--- a/docs/css/default.css
+++ b/docs/css/default.css
@@ -229,7 +229,7 @@ div.centered-table+p {
}
.red {
- background: #de332e;
+ background: rgb(202, 68, 94);
color: #fff;
}
diff --git a/docs/css/main.scss b/docs/css/main.scss
deleted file mode 100644
index f8354e6de..000000000
--- a/docs/css/main.scss
+++ /dev/null
@@ -1,298 +0,0 @@
----
-# Only the main Sass file needs front matter (the dashes are enough)
----
-@charset "utf-8";
-
-@import 'https://fonts.googleapis.com/css?family=Source+Code+Pro';
-
-// Our variables
-$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-$base-font-size: 16px;
-$code-font-family: 'Source Code Pro', sans-serif;
-$base-font-weight: 400;
-$small-font-size: $base-font-size * 0.875;
-$base-line-height: 1.5;
-
-$spacing-unit: 30px;
-
-$text-color: #efefef;
-$background-color: #002B36;
-$brand-color: #2a7ae2;
-
-
-$blue: #3498db;
-$blue-light: rgba(52, 152, 219, 0.12);
-$grey: #f8f8f8;
-$red: #de332e;
-
-$link-color: $blue;
-
-// content area
-$distance-top: 80px;
-$content-width: 1150px;
-$on-palm: 600px;
-$on-laptop: 800px;
-$toc-width: 220px;
-// Minima also includes a mixin for defining media queries.
-// Use media queries like this:
-// @include media-query($on-palm) {
-// .wrapper {
-// padding-right: $spacing-unit / 2;
-// padding-left: $spacing-unit / 2;
-// }
-// }
-@import "minima";
-
-html {
- box-sizing: border-box;
-}
-
-*, *:before, *:after {
- box-sizing: inherit;
-}
-
-*:focus {
- outline: none;
-}
-
-a, a:focus, a:hover, a:visited {
- color: $link-color;
-}
-
-div#container {
- position: relative;
- max-width: $content-width;
- margin: 0 auto;
- overflow: hidden;
-
- > a.logo-container {
- display: none;
- }
-
- div#content {
- position: relative;
- margin-top: $distance-top;
- width: $content-width - $toc-width;
- float: right;
- display: inline;
-
- > h1.title {
- margin-bottom: 0;
- }
-
- > h2.subtitle {
- font-size: 20px;
- }
- }
-
- div#toc {
- float: left;
- margin-top: $distance-top;
- padding-right: 20px;
- width: $toc-width;
-
- form#search-form {
- input#search-box {
- width: 100%;
- border: 0;
- height: 24px;
- font-size: 14px;
- padding-left: 4px;
- }
-
- input#search-button {
- margin-top: 3px;
- }
- }
-
- > div {
- position: fixed;
- top: $distance-top;
- bottom: auto;
- max-width: $toc-width;
-
- a > div#scala-logo {
- width: 64px;
- margin-bottom: 25px;
-
- > svg path {
- fill: $red;
- }
- }
-
- ul#categories {
- list-style-type: none;
- margin: 0;
- padding: 0;
- background-color: transparent;
-
- > li {
- border-right: 2px solid transparent;
- margin-bottom: 15px;
-
- ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
- background: transparent;
-
- li:hover {
- border-right: 3px solid $blue;
- background-color: $blue-light;
-
- a:link, a:visited, a:hover, a:focus {
- text-decoration: none;
- }
- }
- }
- }
- }
- }
- }
-}
-
-div.edit-docs {
- position: absolute;
- top: 8px;
- right: 0;
-}
-
-h1#search {
- margin-top: 50px;
-}
-
-form#search-bar {
- width: 100%;
- > input {
- width: 100%;
- border: 0;
- height: 24px;
- font-size: 14px;
- padding-left: 4px;
- }
-}
-
-div.author-container {
- height: 50px;
- margin-bottom: 15px;
- > img {
- float: left;
- width: 100px;
- border-radius: 50%;
- }
-
- > div.author-info {
- color: rgba(255,255,255,0.45);
- float: left;
- }
-}
-
-div.author-container.spaced {
- height: 100px;
-
- > div.author-info {
- margin: 28px 0 0 20px;
- }
-}
-
-ul.post-list {
- > li+li {
- margin-top: 15px;
- }
-
- > li {
- div.date {
- color: rgba(255,255,255,0.55);
- }
- }
-}
-
-pre, code, code.hljs {
- padding: 0;
- border: 0;
- border-radius: 3px;
- background-color: $grey;
- color: $background-color;
- font-family: $code-font-family;
-}
-
-code {
- padding-left: 0.1em;
- padding-right: 0.1em;
-}
-
-pre {
- padding: 0.5em;
- background-color: $grey !important;
-}
-
-body {
- font: 400 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
- color: $text-color;
-}
-
-@include media-query(1166px) {
- div#container {
- max-width: 1000px;
-
- div#content {
- width: 1000px - $toc-width;
- }
- }
-}
-
-@include media-query(1016px) {
- div#container {
- max-width: 900px;
-
- div#content {
- width: 900px - $toc-width;
- }
- }
-}
-
-@include media-query(915px) {
- body {
- min-width: 0;
- }
-
- div#container {
- max-width: none;
- padding: 12px;
-
- a.logo-container {
- display: block;
- > div#scala-logo-mobile {
- width: 64px;
- margin: 15px auto 0;
-
- > svg path {
- fill: $red;
- }
- }
- }
-
- div#toc {
- float: none;
- width: 100%;
- height: auto;
- margin-top: 0;
-
- > div {
- top: 0;
- position: relative;
-
- svg {
- display: none;
- top: auto;
- }
- }
- }
- div#content {
- float: none;
- width: 100%;
- height: auto;
- max-width: none;
- }
- }
-}
diff --git a/docs/docs/contributing/eclipse.md b/docs/docs/contributing/eclipse.md
index 0e4125df0..a7deab804 100644
--- a/docs/docs/contributing/eclipse.md
+++ b/docs/docs/contributing/eclipse.md
@@ -1,6 +1,6 @@
---
-layout: default
-title: "Building Dotty with Eclipse"
+layout: doc-page
+title: Building Dotty with Eclipse
---
Build setup
diff --git a/docs/docs/contributing/getting-started.md b/docs/docs/contributing/getting-started.md
index 4c7299914..26862e790 100644
--- a/docs/docs/contributing/getting-started.md
+++ b/docs/docs/contributing/getting-started.md
@@ -1,6 +1,6 @@
---
-layout: default
-title: "Getting Started"
+layout: doc-page
+title: Getting Started
---
Talks on Dotty
@@ -23,7 +23,7 @@ Compiling and Running
---------------------
Start by cloning the repository:
-```none
+```bash
$ git clone https://github.com/lampepfl/dotty.git
$ cd dotty
```
@@ -31,7 +31,7 @@ $ cd dotty
Dotty provides a standard sbt build: compiling, running and starting a repl can
all be done from within sbt using
-```none
+```bash
$ sbt
> dotc tests/pos/HelloWorld.scala
> dotr HelloWorld
@@ -50,7 +50,7 @@ there is also a bash script that can be used in the same way:
Starting a REPL
---------------
-```none
+```bash
$ sbt
> repl
Welcome to Scala.next (pre-alpha) (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
@@ -61,6 +61,6 @@ scala>
or via bash:
-```none
+```bash
$ ./bin/dotr
```
diff --git a/docs/docs/contributing/intellij-idea.md b/docs/docs/contributing/intellij-idea.md
index 9231f209a..5f477bef8 100644
--- a/docs/docs/contributing/intellij-idea.md
+++ b/docs/docs/contributing/intellij-idea.md
@@ -1,6 +1,6 @@
---
-layout: default
-title: "Building Dotty with Intellij IDEA"
+layout: doc-page
+title: Building Dotty with Intellij IDEA
---
Dotty compiler support is available in the [Scala plugin nightly] starting
diff --git a/docs/docs/contributing/workflow.md b/docs/docs/contributing/workflow.md
index fb8da0da3..6e7f5b9a0 100644
--- a/docs/docs/contributing/workflow.md
+++ b/docs/docs/contributing/workflow.md
@@ -1,6 +1,6 @@
---
-layout: default
-title: "Workflow"
+layout: doc-page
+title: Workflow
---
This document details common workflow patterns when working with Dotty.
@@ -19,13 +19,14 @@ git clone -b dotty-library https://github.com/DarkDimius/scala.git scala-scala
From sbt:
-```none
+```bash
+$ sbt
> dotc <OPTIONS> <FILE>
```
From terminal:
-```none
+```bash
$ ./bin/dotc <OPTIONS> <FILE>
```
@@ -47,7 +48,7 @@ Additional logging information can be obtained by changes some `noPrinter` to
## Running tests ##
-```none
+```bash
$ sbt
> partest --show-diff --verbose
```
@@ -55,7 +56,7 @@ $ sbt
## Running single tests ##
To test a specific test tests/x/y.scala (for example tests/pos/t210.scala):
-```none
+```bash
> partest-only-no-bootstrap --show-diff --verbose tests/partest-generated/x/y.scala
```
@@ -67,7 +68,7 @@ the way partest has been set up.
There is no power mode for the REPL yet, but you can inspect types with the
type stealer:
-```none
+```bash
> repl
scala> import dotty.tools.DottyTypeStealer._; import dotty.tools.dotc.core._; import Contexts._,Types._
```
diff --git a/docs/docs/index.md b/docs/docs/index.md
index 0d9bc6b6f..4ee381812 100644
--- a/docs/docs/index.md
+++ b/docs/docs/index.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Dotty Documentation"
---
diff --git a/docs/docs/internals/backend.md b/docs/docs/internals/backend.md
index 47974b5ff..e1fd20da2 100644
--- a/docs/docs/internals/backend.md
+++ b/docs/docs/internals/backend.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Backend Internals"
---
@@ -33,18 +33,19 @@ BCodeIdiomatic ----------------> utilities for code generation, e.g.
### Data Flow ###
Compiler creates a `BCodePhase`, calls `runOn(compilationUnits)`.
- * initializes fields of `GenBCode` defined in `BCodeTypes` (BType maps,
- common BTypes like `StringReference`)
- * initialize `primitives` map defined in `scalaPrimitives` (maps primitive
- members, like `int.+`, to bytecode instructions)
- * creates `BytecodeWriter`, `JMirrorBuilder` and `JBeanInfoBuilder` instances
- (on each compiler run)
- * `buildAndSendToDisk(units)`: uses work queues, see below.
- - `BCodePhase.addToQ1` adds class trees to `q1`
- - `Worker1.visit` creates ASM `ClassNodes`, adds to `q2`. It creates one
- `PlainClassBuilder` for each compilation unit.
- - `Worker2.addToQ3` adds byte arrays (one for each class) to `q3`
- - `BCodePhase.drainQ3` writes byte arrays to disk
+
+* initializes fields of `GenBCode` defined in `BCodeTypes` (BType maps,
+ common BTypes like `StringReference`)
+* initialize `primitives` map defined in `scalaPrimitives` (maps primitive
+ members, like `int.+`, to bytecode instructions)
+* creates `BytecodeWriter`, `JMirrorBuilder` and `JBeanInfoBuilder` instances
+ (on each compiler run)
+* `buildAndSendToDisk(units)`: uses work queues, see below.
+ - `BCodePhase.addToQ1` adds class trees to `q1`
+ - `Worker1.visit` creates ASM `ClassNodes`, adds to `q2`. It creates one
+ `PlainClassBuilder` for each compilation unit.
+ - `Worker2.addToQ3` adds byte arrays (one for each class) to `q3`
+ - `BCodePhase.drainQ3` writes byte arrays to disk
### Architecture ###
diff --git a/docs/docs/internals/benchmarks.md b/docs/docs/internals/benchmarks.md
index 4d24ec0ff..f2ddbd6d0 100644
--- a/docs/docs/internals/benchmarks.md
+++ b/docs/docs/internals/benchmarks.md
@@ -1,5 +1,10 @@
+---
+layout: doc-page
+title: "Benchmarks"
+---
+
The regression benchmark infrastructure is still under construction.
A preview can be found below:
-- [d-d.me/tnc/dotty/web/](https://d-d.me/tnc/dotty/web/) \ No newline at end of file
+- [d-d.me/tnc/dotty/web/](https://d-d.me/tnc/dotty/web/)
diff --git a/docs/docs/internals/classpaths.md b/docs/docs/internals/classpaths.md
index 0038b5de0..1a137c1ea 100644
--- a/docs/docs/internals/classpaths.md
+++ b/docs/docs/internals/classpaths.md
@@ -1,3 +1,8 @@
+---
+layout: doc-page
+title: Classpaths
+---
+
When ran from the `dotty` script, this is the classloader stack:
```
diff --git a/docs/docs/internals/contexts.md b/docs/docs/internals/contexts.md
index 09cbb40c5..df998d49b 100644
--- a/docs/docs/internals/contexts.md
+++ b/docs/docs/internals/contexts.md
@@ -1,6 +1,6 @@
---
-layout: default
-title: "Contexts"
+layout: doc-page
+title: Contexts
---
The `Context` contains the state of the compiler, for example
diff --git a/docs/dotc-internals/core-data-structures.md b/docs/docs/internals/core-data-structures.md
index eddc3398c..623114aa3 100644
--- a/docs/dotc-internals/core-data-structures.md
+++ b/docs/docs/internals/core-data-structures.md
@@ -1,10 +1,14 @@
+---
+layout: doc-page
+title: Core Data Structures
+---
+
(The following is work in progress)
## Symbols and SymDenotations
- why symbols are not enough: their contents change all the time
- - they change themselvesSo a `Symbol
-
+ - they change themselvesSo a `Symbol`
- reference: string + sig
diff --git a/docs/docs/internals/dotc-scalac.md b/docs/docs/internals/dotc-scalac.md
index f41f21370..9a7de2cb9 100644
--- a/docs/docs/internals/dotc-scalac.md
+++ b/docs/docs/internals/dotc-scalac.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Differences between Scalac and Dotty"
---
diff --git a/docs/docs/internals/higher-kinded-v2.md b/docs/docs/internals/higher-kinded-v2.md
index 3019e3031..4676d3ebd 100644
--- a/docs/docs/internals/higher-kinded-v2.md
+++ b/docs/docs/internals/higher-kinded-v2.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Higher-Kinded Types in Dotty"
---
diff --git a/docs/docs/internals/overall-structure.md b/docs/docs/internals/overall-structure.md
index 1b4e22f1b..78cc26c8d 100644
--- a/docs/docs/internals/overall-structure.md
+++ b/docs/docs/internals/overall-structure.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Dotty Overall Structure"
---
diff --git a/docs/docs/internals/periods.md b/docs/docs/internals/periods.md
index bb161b7b8..257d8504e 100644
--- a/docs/docs/internals/periods.md
+++ b/docs/docs/internals/periods.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Dotc's concept of time"
---
diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md
index 7c8cb1ea2..b7d5936c2 100644
--- a/docs/docs/internals/syntax.md
+++ b/docs/docs/internals/syntax.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Scala Syntax Summary"
---
diff --git a/docs/docs/internals/type-system.md b/docs/docs/internals/type-system.md
index e3a563c21..eda1cfbde 100644
--- a/docs/docs/internals/type-system.md
+++ b/docs/docs/internals/type-system.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Type System"
---
diff --git a/docs/docs/usage/cbt-projects.md b/docs/docs/usage/cbt-projects.md
index 291813b91..d4915fe39 100644
--- a/docs/docs/usage/cbt-projects.md
+++ b/docs/docs/usage/cbt-projects.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Using Dotty with cbt"
---
@@ -9,7 +9,7 @@ cbt comes with built-in dotty support. Follow the
```scala
// build/build.scala
import cbt._
-class Build(val context: Context) extends Dotty{
+class Build(val context: Context) extends Dotty {
...
}
```
diff --git a/docs/docs/usage/dottydoc.md b/docs/docs/usage/dottydoc.md
new file mode 100644
index 000000000..d064cb5ca
--- /dev/null
+++ b/docs/docs/usage/dottydoc.md
@@ -0,0 +1,260 @@
+---
+layout: doc-page
+title: Dottydoc
+---
+
+Dottydoc is a tool to generate a combined documentation and API reference for
+your project.
+
+In previous versions of the Scaladoc tool, there is a big divide between what
+is documentation and what is API reference. Dottydoc allows referencing, citing
+and rendering parts of your API in your documentation, thus allowing the two to
+blend naturally.
+
+To do this, Dottydoc is very similar to what [Jekyll](http://jekyllrb.com/)
+provides in form of static site generation. As you probably guessed, this
+whole site was created using Dottydoc.
+
+Creating a site is just as simple as in Jekyll. The site root contains the
+layout of the site and all files placed here will be either considered static,
+or processed for template expansion.
+
+The files that are considered for template expansion must end in `*.{html,md}`
+and will from here on be referred to as "template files" or "templates".
+
+A simple "hello world" site could look something like this:
+
+```none
+├── docs
+│ └── getting-started.md
+└── index.html
+```
+
+This will give you a site with the following endpoints:
+
+```none
+_site/index.html
+_site/docs/getting-started.html
+```
+
+Just as with Jekyll, the site is rendered in a `_site` directory.
+
+Using existing Templates and Layouts
+====================================
+Dottydoc uses the [Liquid](https://shopify.github.io/liquid/) templating engine
+and provides a number of custom filters and tags specific to Scala
+documentation.
+
+In Dottydoc, all templates can contain YAML front-matter. The front-matter
+is parsed and put into the `page` variable available in templates via Liquid.
+
+To perform template expansion, Dottydoc looks at `layout` in the front-matter.
+Here's a simple example of the templating system in action, `index.html`:
+
+```html
+---
+layout: main
+---
+
+<h1>Hello world!</h1>
+```
+
+With a simple main template like this:
+
+{% raw %}
+```html
+<html>
+ <head>
+ <title>Hello, world!</title>
+ </head>
+ <body>
+ {{ content }}
+ </body>
+</html>
+```
+
+Would result in `{{ content }}` being replaced by `<h1>Hello world!</h1>` from
+the `index.html` file.
+{% endraw %}
+
+Layouts must be placed in a `_layouts` directory in the site root:
+
+```none
+├── _layouts
+│ └── main.html
+├── docs
+│ └── getting-started.md
+└── index.html
+```
+
+It is also possible to use one of the [default layouts](#default-layouts) that ship with Dottydoc.
+
+Blog
+====
+Dottydoc also allows for a simple blogging platform in the same vein as Jekyll.
+Blog posts are placed within the `./blog/_posts` directory and have to be on
+the form `year-month-day-title.{md,html}`.
+
+An example of this would be:
+
+```none
+├── blog
+│ └── _posts
+│ └── 2016-12-05-implicit-function-types.md
+└── index.html
+```
+
+To be rendered as templates, each blog post should have front-matter and a
+`layout` declaration.
+
+The posts are also available in the variable `site.posts` throughout the site.
+The fields of these objects are the same as in
+[BlogPost](dotty.tools.dottydoc.staticsite.BlogPost).
+
+Includes
+========
+In Liquid, there is a concept of include tags, these are used in templates to
+include other de facto templates:
+
+```html
+<div class="container">
+ {% raw %}{% include "sidebar.html" %}{% endraw %}
+</div>
+```
+
+You can leave out the file extension if your include ends in `.html`.
+
+Includes need to be kept in `_includes` in the site root. Dottydoc provides a
+couple of [default includes](#default-includes), but the user-specified
+includes may override these.
+
+An example structure with an include file "sidebar.html":
+
+```none
+├── _includes
+│ └── sidebar.html
+├── blog
+│ ├── _posts
+│ │ └── 2016-12-05-implicit-function-types.md
+│ └── index.md
+└── index.html
+```
+
+Sidebar
+=======
+Dottydoc gives you the ability to create your own custom table of contents,
+this can either be achieved by overriding the `toc.html` include - or by
+providing a `sidebar.yml` file in the site root:
+
+```yaml
+sidebar:
+ - title: Blog
+ url: blog/index.html
+ - title: Docs
+ url: docs/index.html
+ - title: Usage
+ subsection:
+ - title: Dottydoc
+ url: docs/usage/dottydoc.html
+ - title: sbt-projects
+ url: docs/usage/sbt-projects.html
+```
+
+The `sidebar` key is mandatory, as well as `title` for each element. The
+default table of contents allows you to have subsections - albeit the current
+depth limit is 2 - we'd love to see this change, contributions welcome!
+
+The items which have the `subsection` key, may not have a `url` key in the
+current scheme. A site root example with this could be:
+
+```none
+├── blog
+│ └── _posts
+│ └── 2016-12-05-implicit-function-types.md
+├── index.html
+└── sidebar.yml
+```
+
+Dottydoc Specific Tags and Behavior
+====================================
+Linking to API
+--------------
+If you for instance, want to link to `scala.collection.immutable.Seq` in a
+markdown file, you can simply use the canonical path in your url:
+
+```markdown
+[Seq](scala.collection.immutable.Seq)
+```
+
+Linking to members is done in the same fashion:
+
+```markdown
+[Seq](scala.collection.immutable.Seq.isEmpty)
+```
+
+Dottydoc denotes objects by ending their names in "$". To select `Object.range`
+you'd therefore write:
+
+```markdown
+[Object.range](scala.collection.immutable.List$.range)
+```
+
+Rendering Docstrings
+--------------------
+Sometimes you end up duplicating the docstring text in your documentation,
+therefore Dottydoc makes it easy to render this inline:
+
+```html
+{% raw %}{% docstring "scala.collection.immutable.Seq" %}{% endraw %}
+```
+
+Other extensions
+----------------
+We would love to have your feedback on what you think would be good in order to
+render the documentation you want! Perhaps you'd like to render method
+definitions or members? Let us know by filing
+[issues](https://github.com/lampepfl/dotty/issues/new)!
+
+Default Layouts
+===============
+main.html
+---------
+A wrapper for all other layouts, includes a default `<head>` with included
+JavaScripts and CSS style-sheets.
+
+### Variables ###
+* `content`: placed in `<body>` tag
+* `extraCSS`: a list of relative paths to extra CSS style-sheets for the site
+* `extraJS`: a list of relative paths to extra JavaScripts for the site
+* `title`: the `<title>` of the page
+
+sidebar.html
+------------
+Sidebar uses `main.html` as its parent layout. It adds a sidebar generated from
+a YAML file (if exists), as well as the index for the project API.
+
+### Variables ###
+* `content`: placed in a `<div>` with class `content-body`
+* `docs`: the API docs generated from supplied source files, this is included by
+ default and does not need to be specified.
+
+doc-page.html
+-------------
+Doc page is used for pages that need a sidebar and provides a small wrapper for
+the included {% raw %}`{{ content}}`{% endraw %}.
+
+api-page.html
+-------------
+The last two layouts are special, in that they are treated specially by
+Dottydoc. The input to the API page is a documented
+[Entity](dotty.tools.dottydoc.model.Entity). As such, this page can be changed
+to alter the way Dottydoc renders API documentation.
+
+blog-page.html
+--------------
+A blog page uses files placed in `./blog/_posts/` as input to render a blog.
+
+Default Includes
+================
+* `scala-logo.svg`: the scala in dotty version as svg
+* `toc.html`: the default table of contents template
diff --git a/docs/docs/usage/migrating.md b/docs/docs/usage/migrating.md
index eb76571e5..5a2f64be3 100644
--- a/docs/docs/usage/migrating.md
+++ b/docs/docs/usage/migrating.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Migrating to Dotty"
---
@@ -17,15 +17,15 @@ Most `sym.isProperty` methods don't exist in dotc, test for flags instead. See
[dotc vs scalac: Trees, Symbols, Types & Denotations]
### Logging, Error Reporting, Failures ###
-
There are various kinds of logging:
- * Errors, warnings, etc: `ctx.inform`, `ctx.warning`, `ctx.error`, ...
- * Log messages displayed under `-Ylog:phase`: `log(msg)` in scalac =>
- `ctx.log(msg)` in dotc
- * Debug-Log messages displayed under `-Ydebug -Ylog:<phase>`: `debuglog(msg)`
- in scalac => `ctx.debuglog(msg)` in dotc
- * Assertions: `assert(invariant)`
- * Fatal errors: `abort(msg)` in scalac => `throw new
+
+* Errors, warnings, etc: `ctx.inform`, `ctx.warning`, `ctx.error`, ...
+* Log messages displayed under `-Ylog:phase`: `log(msg)` in scalac =>
+ `ctx.log(msg)` in dotc
+* Debug-Log messages displayed under `-Ydebug -Ylog:<phase>`: `debuglog(msg)`
+ in scalac => `ctx.debuglog(msg)` in dotc
+* Assertions: `assert(invariant)`
+* Fatal errors: `abort(msg)` in scalac => `throw new
dotty.tools.dotc.FatalError(msg)` in dotc
diff --git a/docs/docs/usage/sbt-projects.md b/docs/docs/usage/sbt-projects.md
index b4eb5136d..2f27492a7 100644
--- a/docs/docs/usage/sbt-projects.md
+++ b/docs/docs/usage/sbt-projects.md
@@ -1,5 +1,5 @@
---
-layout: default
+layout: doc-page
title: "Using Dotty with sbt"
---
diff --git a/docs/images/olivier.jpeg b/docs/images/olivier.jpeg
new file mode 100644
index 000000000..7c11e1de3
--- /dev/null
+++ b/docs/images/olivier.jpeg
Binary files differ
diff --git a/docs/images/scala-logo.svg b/docs/images/scala-logo.svg
index 6b8f110b7..1fb642c8b 100644
--- a/docs/images/scala-logo.svg
+++ b/docs/images/scala-logo.svg
@@ -1,19 +1,30 @@
-<svg width="64" height="110" xmlns="http://www.w3.org/2000/svg">
- <g>
- <title>background</title>
- <rect x="-1" y="-1" width="9.664668" height="15.173648" id="canvas_background" fill="none"/>
- </g>
-
- <g>
- <title>Layer 1</title>
- <g id="logo">
- <g opacity="0.61" id="svg_1">
- <path fill="#FFFFFF" d="m0.5,41.9c0,0 62.9,6.3 62.9,16.8l0,-25.2c0,0 0,-10.5 -62.9,-16.8l0,9.8l0,15.4z" id="svg_2"/>
- <path fill="#FFFFFF" d="m0.5,75.5c0,0 62.9,6.3 62.9,16.8l0,-25.2c0,0 0,-10.5 -62.9,-16.8l0,25.2z" id="svg_3"/>
- </g>
- <path fill="#FFFFFF" d="m63.5,0l0,25.2c0,0 0,10.5 -62.9,16.8l0,-25.3c-0.1,0 62.9,-6.2 62.9,-16.7" id="svg_4"/>
- <path fill="#FFFFFF" d="m0.5,50.3c0,0 62.9,-6.3 62.9,-16.8l0,25.2c0,0 0,10.5 -62.9,16.8l0,-25.2z" id="svg_5"/>
- <path fill="#FFFFFF" d="m0.5,109l0,-25.2c0,0 62.9,-6.3 62.9,-16.8l0,25.2c0.1,0.1 0.1,10.5 -62.9,16.8" id="svg_6"/>
- </g>
- </g>
-</svg> \ No newline at end of file
+<svg width="64px" height="109px" viewBox="0 0 64 109" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="logo-background" transform="translate(0.000000, 16.000000)" fill="#ccc">
+ <path d="M0.5,59.5 C0.5,59.5 63.4,65.8 63.4,76.3 L63.4,51.1 C63.4,51.1 63.4,40.6 0.5,34.3 L0.5,59.5 L0.5,59.5 Z" id="logo-background-bottom"></path>
+ <path d="M0.5,25.9 C0.5,25.9 63.4,32.2 63.4,42.7 L63.4,17.5 C63.4,17.5 63.4,7 0.5,0.7 L0.5,10.5 L0.5,25.9 L0.5,25.9 Z" id="logo-background-top"></path>
+ </g>
+ <g id="logo-foreground" fill="#ffffff">
+ <path d="M0.5,109 L0.5,83.8 C0.5,83.8 63.4,77.5 63.4,67 L63.4,92.2 C63.5,92.3 63.5,102.7 0.5,109" id="Logo_Foreground_Bottom"></path>
+ <path d="M0.5,50.3 C0.5,50.3 63.4,44 63.4,33.5 L63.4,58.7 C63.4,58.7 63.4,69.2 0.5,75.5 L0.5,50.3 L0.5,50.3 Z" id="Logo_Foreground_Middle"></path>
+ <path d="M63.5,0 L63.5,25.2 C63.5,25.2 63.5,35.7 0.6,42 L0.6,16.7 C0.5,16.7 63.5,10.5 63.5,0" id="logo-foreground-top"></path>
+ </g>
+ <g id="dots" transform="translate(4.000000, 10.000000)" fill="#B6B6B6">
+ <g id="bottom" transform="translate(0.000000, 67.500000)">
+ <path d="M1.4471104,12.2885536 C1.45019313,12.2881864 1.45019313,12.2881864 1.45327704,12.2878189 C1.91768952,12.2324787 2.24930811,11.8111359 2.1939679,11.3467234 C2.13862768,10.8823109 1.71728488,10.5506923 1.2528724,10.6060325 C1.24980572,10.606398 1.24980572,10.606398 1.24674021,10.6067632 C0.782326598,10.6620939 0.450699376,11.0834299 0.506030077,11.5478435 C0.561360778,12.0122571 0.982696791,12.3438844 1.4471104,12.2885536 L1.4471104,12.2885536 Z M9.34858965,12.1304907 C9.35409106,12.129756 9.35409106,12.129756 9.35959333,12.129021 C10.1807278,12.019341 10.7574756,11.2647668 10.6477955,10.4436323 C10.5381155,9.62249789 9.78354128,9.04575011 8.96240683,9.15543014 C8.95693539,9.15616095 8.95693539,9.15616095 8.95146479,9.15689157 C8.13032806,9.26655457 7.55356464,10.0211168 7.66322765,10.8422536 C7.77289065,11.6633903 8.52745292,12.2401537 9.34858965,12.1304907 L9.34858965,12.1304907 Z M17.0066591,11.0493128 C17.0121188,11.0484984 17.0121188,11.0484984 17.0175789,11.0476838 C17.8369369,10.9254384 18.4020584,10.1621181 18.279813,9.34276003 C18.1575677,8.52340201 17.3942473,7.95828052 16.5748893,8.08052587 C16.5694641,8.08133528 16.5694641,8.08133528 16.5640392,8.08214454 C15.7446783,8.20437064 15.1795389,8.96767771 15.301765,9.78703861 C15.4239911,10.6063995 16.1872982,11.1715389 17.0066591,11.0493128 L17.0066591,11.0493128 Z M24.8225082,10.4232459 C24.8297684,10.4220275 24.8297684,10.4220275 24.8370287,10.420809 C25.922252,10.2386672 26.6543441,9.21126476 26.4722023,8.12604147 C26.2900605,7.04081818 25.2626581,6.30872601 24.1774348,6.49086783 C24.1702314,6.4920768 24.1702314,6.4920768 24.1630282,6.49328559 C23.0777996,6.67539597 22.3456777,7.70277717 22.5277881,8.78800574 C22.7098984,9.87323431 23.7372796,10.6053563 24.8225082,10.4232459 L24.8225082,10.4232459 Z M32.4725265,9.05261002 C33.5532108,8.84532993 34.2612448,7.80122849 34.0539647,6.72054419 C33.8466846,5.63985989 32.8025831,4.93182589 31.7218988,5.13910599 C31.714724,5.14048211 31.714724,5.14048211 31.7075489,5.14185807 C30.6268567,5.34909665 29.9187826,6.39317088 30.1260211,7.47386314 C30.3332597,8.5545554 31.3773339,9.26262952 32.4580262,9.05539095 C32.4652764,9.05400057 32.4652764,9.05400057 32.4725265,9.05261002 Z M39.8723866,6.89476879 C39.877909,6.8935242 39.877909,6.8935242 39.883431,6.89227947 C40.6915794,6.71010471 41.1990314,5.90728916 41.0168566,5.09914075 C40.8346818,4.29099233 40.0318663,3.78354042 39.2237179,3.96571517 C39.218279,3.96694116 39.218279,3.96694116 39.2128397,3.96816703 C38.404681,4.15029588 37.8971834,4.9530826 38.0793123,5.76124136 C38.2614411,6.56940012 39.0642279,7.07689764 39.8723866,6.89476879 L39.8723866,6.89476879 Z M47.4276119,5.00828445 C47.4329844,5.00678549 47.4329844,5.00678549 47.4383562,5.00528637 C48.2362896,4.78258973 48.7026111,3.95520561 48.4799145,3.15727221 C48.2572179,2.35933881 47.4298337,1.89301728 46.6319003,2.11571391 C46.6266645,2.1171751 46.6266645,2.1171751 46.6214279,2.11863616 C45.8234736,2.34125773 45.3570742,3.16859798 45.5796958,3.96655233 C45.8023173,4.76450667 46.6296576,5.23090603 47.4276119,5.00828445 L47.4276119,5.00828445 Z M54.419759,2.30643871 C54.8556933,2.13695884 55.0716973,1.6461737 54.9022174,1.21023941 C54.7327376,0.774305114 54.2419524,0.558301127 53.8060181,0.727780997 C53.8032127,0.728871549 53.8032127,0.728871549 53.8004064,0.729962021 C53.3644359,0.89934874 53.148327,1.39008772 53.3177137,1.82605822 C53.4871005,2.26202871 53.9778394,2.47813756 54.4138099,2.30875084 C54.4167849,2.30759485 54.4167849,2.30759485 54.419759,2.30643871 Z" id="Shape"></path>
+ <path d="M1.67760355,20.096503 C1.68306395,20.0958524 1.68306395,20.0958524 1.68852642,20.0952015 C2.51113381,19.9971782 3.09852524,19.2508595 3.00050189,18.4282521 C2.90247854,17.6056447 2.15615986,17.0182533 1.33355246,17.1162767 C1.3281205,17.1169239 1.3281205,17.1169239 1.3226906,17.1175709 C0.500081196,17.2155774 -0.0873255124,17.961884 0.0106809923,18.7844934 C0.108687497,19.6071028 0.854994145,20.1945095 1.67760355,20.096503 L1.67760355,20.096503 Z M9.34858965,19.1274206 C9.35409106,19.1266859 9.35409106,19.1266859 9.35959333,19.1259509 C10.1807278,19.0162709 10.7574756,18.2616967 10.6477955,17.4405622 C10.5381155,16.6194278 9.78354128,16.04268 8.96240683,16.15236 C8.95693539,16.1530908 8.95693539,16.1530908 8.95146479,16.1538215 C8.13032806,16.2634845 7.55356464,17.0180467 7.66322765,17.8391835 C7.77289065,18.6603202 8.52745292,19.2370836 9.34858965,19.1274206 L9.34858965,19.1274206 Z M17.1767435,18.6256231 C17.1839958,18.6245412 17.1839958,18.6245412 17.1912486,18.6234592 C18.27963,18.4610765 19.0303002,17.4471319 18.8679175,16.3587506 C18.7055348,15.2703693 17.6915903,14.519699 16.6032089,14.6820817 C16.5960024,14.6831569 16.5960024,14.6831569 16.5887964,14.6842319 C15.5004112,14.846589 14.7497172,15.8605159 14.9120743,16.948901 C15.0744314,18.0372862 16.0883584,18.7879802 17.1767435,18.6256231 L17.1767435,18.6256231 Z M24.8370287,17.4177379 C25.922252,17.2355961 26.6543441,16.2081937 26.4722023,15.1229704 C26.2900605,14.0377471 25.2626581,13.3056549 24.1774348,13.4877968 C24.1702314,13.4890057 24.1702314,13.4890057 24.1630282,13.4902145 C23.0777996,13.6723249 22.3456777,14.6997061 22.5277881,15.7849347 C22.7098984,16.8701632 23.7372796,17.6022852 24.8225082,17.4201748 C24.8297684,17.4189565 24.8297684,17.4189565 24.8370287,17.4177379 Z M32.4725265,16.061085 C33.5532108,15.853199 34.2612448,14.8060455 34.0539647,13.7222022 C33.8466846,12.6383589 32.8025831,11.9282552 31.7218988,12.1361412 C31.714724,12.1375214 31.714724,12.1375214 31.7075489,12.1389013 C30.6268567,12.3467457 29.9187826,13.3938719 30.1260211,14.4777232 C30.3332597,15.5615745 31.3773339,16.2717185 32.4580262,16.0638741 C32.4652764,16.0624797 32.4652764,16.0624797 32.4725265,16.061085 Z M40.0707225,14.4695476 C40.0780573,14.4678946 40.0780573,14.4678946 40.0853916,14.4662413 C41.158768,14.2242783 41.8327617,13.1579849 41.5907986,12.0846085 C41.3488355,11.011232 40.2825422,10.3372384 39.2091657,10.5792015 C39.2019419,10.5808298 39.2019419,10.5808298 39.1947175,10.582458 C38.1213273,10.8243601 37.447273,11.8906152 37.6891752,12.9640053 C37.9310773,14.0373955 38.9973324,14.7114498 40.0707225,14.4695476 L40.0707225,14.4695476 Z M47.4276119,12.0082845 C47.4329844,12.0067855 47.4329844,12.0067855 47.4383562,12.0052864 C48.2362896,11.7825897 48.7026111,10.9552056 48.4799145,10.1572722 C48.2572179,9.35933881 47.4298337,8.89301728 46.6319003,9.11571391 C46.6266645,9.1171751 46.6266645,9.1171751 46.6214279,9.11863616 C45.8234736,9.34125773 45.3570742,10.168598 45.5796958,10.9665523 C45.8023173,11.7645067 46.6296576,12.230906 47.4276119,12.0082845 L47.4276119,12.0082845 Z M54.8999721,9.57562965 C54.9052414,9.57358217 54.9052414,9.57358217 54.9105092,9.57153441 C55.6826371,9.27135123 56.0652239,8.40207131 55.7650408,7.62994336 C55.4648576,6.85781542 54.5955777,6.4752286 53.8234497,6.77541179 C53.8184808,6.77734338 53.8184808,6.77734338 53.8135101,6.77927482 C53.0413181,7.07929302 52.6585455,7.94849117 52.9585637,8.72068323 C53.2585819,9.4928753 54.12778,9.87564785 54.8999721,9.57562965 L54.8999721,9.57562965 Z" id="Shape"></path>
+ <path d="M1.45327704,26.6978168 C1.54647464,26.6867112 1.63432439,26.660866 1.7147722,26.6228911 C2.03520341,26.4716332 2.23820252,26.1279362 2.1939679,25.7567213 C2.13862768,25.2923089 1.71728488,24.9606903 1.2528724,25.0160305 C1.24980572,25.0163959 1.24980572,25.0163959 1.24674021,25.0167611 C0.782326598,25.0720918 0.450699376,25.4934278 0.506030077,25.9578415 C0.561360778,26.4222551 0.982696791,26.7538823 1.4471104,26.6985516 C1.45019313,26.6981843 1.45019313,26.6981843 1.45327704,26.6978168 Z M9.34858965,26.1274206 C9.35409106,26.1266859 9.35409106,26.1266859 9.35959333,26.1259509 C10.1807278,26.0162709 10.7574756,25.2616967 10.6477955,24.4405622 C10.5381155,23.6194278 9.78354128,23.04268 8.96240683,23.15236 C8.95693539,23.1530908 8.95693539,23.1530908 8.95146479,23.1538215 C8.13032806,23.2634845 7.55356464,24.0180467 7.66322765,24.8391835 C7.77289065,25.6603202 8.52745292,26.2370836 9.34858965,26.1274206 L9.34858965,26.1274206 Z M17.0066591,25.0462427 C17.0121188,25.0454283 17.0121188,25.0454283 17.0175789,25.0446136 C17.8369369,24.9223683 18.4020584,24.1590479 18.279813,23.3396899 C18.1575677,22.5203319 17.3942473,21.9552104 16.5748893,22.0774558 C16.5694641,22.0782652 16.5694641,22.0782652 16.5640392,22.0790744 C15.7446783,22.2013005 15.1795389,22.9646076 15.301765,23.7839685 C15.4239911,24.6033294 16.1872982,25.1684688 17.0066591,25.0462427 L17.0066591,25.0462427 Z M24.8225082,24.4201748 C24.8297684,24.4189565 24.8297684,24.4189565 24.8370287,24.4177379 C25.922252,24.2355961 26.6543441,23.2081937 26.4722023,22.1229704 C26.2900605,21.0377471 25.2626581,20.3056549 24.1774348,20.4877968 C24.1702314,20.4890057 24.1702314,20.4890057 24.1630282,20.4902145 C23.0777996,20.6723249 22.3456777,21.6997061 22.5277881,22.7849347 C22.7098984,23.8701632 23.7372796,24.6022852 24.8225082,24.4201748 L24.8225082,24.4201748 Z M32.4725265,23.0495399 C33.5532108,22.8422598 34.2612448,21.7981584 34.0539647,20.7174741 C33.8466846,19.6367898 32.8025831,18.9287558 31.7218988,19.1360359 C31.714724,19.137412 31.714724,19.137412 31.7075489,19.138788 C30.6268567,19.3460265 29.9187826,20.3901008 30.1260211,21.470793 C30.3332597,22.5514853 31.3773339,23.2595594 32.4580262,23.0523208 C32.4652764,23.0509305 32.4652764,23.0509305 32.4725265,23.0495399 Z M39.8723866,20.8947688 C39.877909,20.8935242 39.877909,20.8935242 39.883431,20.8922795 C40.6915794,20.7101047 41.1990314,19.9072892 41.0168566,19.0991407 C40.8346818,18.2909923 40.0318663,17.7835404 39.2237179,17.9657152 C39.218279,17.9669412 39.218279,17.9669412 39.2128397,17.968167 C38.404681,18.1502959 37.8971834,18.9530826 38.0793123,19.7612414 C38.2614411,20.5694001 39.0642279,21.0768976 39.8723866,20.8947688 L39.8723866,20.8947688 Z M47.4276119,19.0082845 C47.4329844,19.0067855 47.4329844,19.0067855 47.4383562,19.0052864 C48.2362896,18.7825897 48.7026111,17.9552056 48.4799145,17.1572722 C48.2572179,16.3593388 47.4298337,15.8930173 46.6319003,16.1157139 C46.6266645,16.1171751 46.6266645,16.1171751 46.6214279,16.1186362 C45.8234736,16.3412577 45.3570742,17.168598 45.5796958,17.9665523 C45.8023173,18.7645067 46.6296576,19.230906 47.4276119,19.0082845 L47.4276119,19.0082845 Z M54.4138099,15.7087505 C54.4167849,15.7075945 54.4167849,15.7075945 54.419759,15.7064383 C54.8556933,15.5369585 55.0716973,15.0461733 54.9022174,14.610239 C54.7327376,14.1743047 54.2419524,13.9583007 53.8060181,14.1277806 C53.8032127,14.1288712 53.8032127,14.1288712 53.8004064,14.1299616 C53.3644359,14.2993484 53.148327,14.7900873 53.3177137,15.2260578 C53.4871005,15.6620283 53.9778394,15.8781372 54.4138099,15.7087505 L54.4138099,15.7087505 Z" id="Shape"></path>
+ </g>
+ <g id="middle" transform="translate(0.000000, 33.900002)">
+ <path d="M1.4471104,12.2885536 C1.45019313,12.2881864 1.45019313,12.2881864 1.45327704,12.2878189 C1.91768952,12.2324787 2.24930811,11.8111359 2.1939679,11.3467234 C2.13862768,10.8823109 1.71728488,10.5506923 1.2528724,10.6060325 C1.24980572,10.606398 1.24980572,10.606398 1.24674021,10.6067632 C0.782326598,10.6620939 0.450699376,11.0834299 0.506030077,11.5478435 C0.561360778,12.0122571 0.982696791,12.3438844 1.4471104,12.2885536 L1.4471104,12.2885536 Z M9.34858965,12.1304907 C9.35409106,12.129756 9.35409106,12.129756 9.35959333,12.129021 C10.1807278,12.019341 10.7574756,11.2647668 10.6477955,10.4436323 C10.5381155,9.62249789 9.78354128,9.04575011 8.96240683,9.15543014 C8.95693539,9.15616095 8.95693539,9.15616095 8.95146479,9.15689157 C8.13032806,9.26655457 7.55356464,10.0211168 7.66322765,10.8422536 C7.77289065,11.6633903 8.52745292,12.2401537 9.34858965,12.1304907 L9.34858965,12.1304907 Z M17.0066591,11.0493128 C17.0121188,11.0484984 17.0121188,11.0484984 17.0175789,11.0476838 C17.8369369,10.9254384 18.4020584,10.1621181 18.279813,9.34276003 C18.1575677,8.52340201 17.3942473,7.95828052 16.5748893,8.08052587 C16.5694641,8.08133528 16.5694641,8.08133528 16.5640392,8.08214454 C15.7446783,8.20437064 15.1795389,8.96767771 15.301765,9.78703861 C15.4239911,10.6063995 16.1872982,11.1715389 17.0066591,11.0493128 L17.0066591,11.0493128 Z M24.8225082,10.4232459 C24.8297684,10.4220275 24.8297684,10.4220275 24.8370287,10.420809 C25.922252,10.2386672 26.6543441,9.21126476 26.4722023,8.12604147 C26.2900605,7.04081818 25.2626581,6.30872601 24.1774348,6.49086783 C24.1702314,6.4920768 24.1702314,6.4920768 24.1630282,6.49328559 C23.0777996,6.67539597 22.3456777,7.70277717 22.5277881,8.78800574 C22.7098984,9.87323431 23.7372796,10.6053563 24.8225082,10.4232459 L24.8225082,10.4232459 Z M32.4725265,9.05261002 C33.5532108,8.84532993 34.2612448,7.80122849 34.0539647,6.72054419 C33.8466846,5.63985989 32.8025831,4.93182589 31.7218988,5.13910599 C31.714724,5.14048211 31.714724,5.14048211 31.7075489,5.14185807 C30.6268567,5.34909665 29.9187826,6.39317088 30.1260211,7.47386314 C30.3332597,8.5545554 31.3773339,9.26262952 32.4580262,9.05539095 C32.4652764,9.05400057 32.4652764,9.05400057 32.4725265,9.05261002 Z M39.8723866,6.89476879 C39.877909,6.8935242 39.877909,6.8935242 39.883431,6.89227947 C40.6915794,6.71010471 41.1990314,5.90728916 41.0168566,5.09914075 C40.8346818,4.29099233 40.0318663,3.78354042 39.2237179,3.96571517 C39.218279,3.96694116 39.218279,3.96694116 39.2128397,3.96816703 C38.404681,4.15029588 37.8971834,4.9530826 38.0793123,5.76124136 C38.2614411,6.56940012 39.0642279,7.07689764 39.8723866,6.89476879 L39.8723866,6.89476879 Z M47.4276119,5.00828445 C47.4329844,5.00678549 47.4329844,5.00678549 47.4383562,5.00528637 C48.2362896,4.78258973 48.7026111,3.95520561 48.4799145,3.15727221 C48.2572179,2.35933881 47.4298337,1.89301728 46.6319003,2.11571391 C46.6266645,2.1171751 46.6266645,2.1171751 46.6214279,2.11863616 C45.8234736,2.34125773 45.3570742,3.16859798 45.5796958,3.96655233 C45.8023173,4.76450667 46.6296576,5.23090603 47.4276119,5.00828445 L47.4276119,5.00828445 Z M54.419759,2.30643871 C54.8556933,2.13695884 55.0716973,1.6461737 54.9022174,1.21023941 C54.7327376,0.774305114 54.2419524,0.558301127 53.8060181,0.727780997 C53.8032127,0.728871549 53.8032127,0.728871549 53.8004064,0.729962021 C53.3644359,0.89934874 53.148327,1.39008772 53.3177137,1.82605822 C53.4871005,2.26202871 53.9778394,2.47813756 54.4138099,2.30875084 C54.4167849,2.30759485 54.4167849,2.30759485 54.419759,2.30643871 Z" id="Shape"></path>
+ <path d="M1.67760355,20.096503 C1.68306395,20.0958524 1.68306395,20.0958524 1.68852642,20.0952015 C2.51113381,19.9971782 3.09852524,19.2508595 3.00050189,18.4282521 C2.90247854,17.6056447 2.15615986,17.0182533 1.33355246,17.1162767 C1.3281205,17.1169239 1.3281205,17.1169239 1.3226906,17.1175709 C0.500081196,17.2155774 -0.0873255124,17.961884 0.0106809923,18.7844934 C0.108687497,19.6071028 0.854994145,20.1945095 1.67760355,20.096503 L1.67760355,20.096503 Z M9.34858965,19.1274206 C9.35409106,19.1266859 9.35409106,19.1266859 9.35959333,19.1259509 C10.1807278,19.0162709 10.7574756,18.2616967 10.6477955,17.4405622 C10.5381155,16.6194278 9.78354128,16.04268 8.96240683,16.15236 C8.95693539,16.1530908 8.95693539,16.1530908 8.95146479,16.1538215 C8.13032806,16.2634845 7.55356464,17.0180467 7.66322765,17.8391835 C7.77289065,18.6603202 8.52745292,19.2370836 9.34858965,19.1274206 L9.34858965,19.1274206 Z M17.1767435,18.6256231 C17.1839958,18.6245412 17.1839958,18.6245412 17.1912486,18.6234592 C18.27963,18.4610765 19.0303002,17.4471319 18.8679175,16.3587506 C18.7055348,15.2703693 17.6915903,14.519699 16.6032089,14.6820817 C16.5960024,14.6831569 16.5960024,14.6831569 16.5887964,14.6842319 C15.5004112,14.846589 14.7497172,15.8605159 14.9120743,16.948901 C15.0744314,18.0372862 16.0883584,18.7879802 17.1767435,18.6256231 L17.1767435,18.6256231 Z M24.8370287,17.4177379 C25.922252,17.2355961 26.6543441,16.2081937 26.4722023,15.1229704 C26.2900605,14.0377471 25.2626581,13.3056549 24.1774348,13.4877968 C24.1702314,13.4890057 24.1702314,13.4890057 24.1630282,13.4902145 C23.0777996,13.6723249 22.3456777,14.6997061 22.5277881,15.7849347 C22.7098984,16.8701632 23.7372796,17.6022852 24.8225082,17.4201748 C24.8297684,17.4189565 24.8297684,17.4189565 24.8370287,17.4177379 Z M32.4725265,16.061085 C33.5532108,15.853199 34.2612448,14.8060455 34.0539647,13.7222022 C33.8466846,12.6383589 32.8025831,11.9282552 31.7218988,12.1361412 C31.714724,12.1375214 31.714724,12.1375214 31.7075489,12.1389013 C30.6268567,12.3467457 29.9187826,13.3938719 30.1260211,14.4777232 C30.3332597,15.5615745 31.3773339,16.2717185 32.4580262,16.0638741 C32.4652764,16.0624797 32.4652764,16.0624797 32.4725265,16.061085 Z M40.0707225,14.4695476 C40.0780573,14.4678946 40.0780573,14.4678946 40.0853916,14.4662413 C41.158768,14.2242783 41.8327617,13.1579849 41.5907986,12.0846085 C41.3488355,11.011232 40.2825422,10.3372384 39.2091657,10.5792015 C39.2019419,10.5808298 39.2019419,10.5808298 39.1947175,10.582458 C38.1213273,10.8243601 37.447273,11.8906152 37.6891752,12.9640053 C37.9310773,14.0373955 38.9973324,14.7114498 40.0707225,14.4695476 L40.0707225,14.4695476 Z M47.4276119,12.0082845 C47.4329844,12.0067855 47.4329844,12.0067855 47.4383562,12.0052864 C48.2362896,11.7825897 48.7026111,10.9552056 48.4799145,10.1572722 C48.2572179,9.35933881 47.4298337,8.89301728 46.6319003,9.11571391 C46.6266645,9.1171751 46.6266645,9.1171751 46.6214279,9.11863616 C45.8234736,9.34125773 45.3570742,10.168598 45.5796958,10.9665523 C45.8023173,11.7645067 46.6296576,12.230906 47.4276119,12.0082845 L47.4276119,12.0082845 Z M54.8999721,9.57562965 C54.9052414,9.57358217 54.9052414,9.57358217 54.9105092,9.57153441 C55.6826371,9.27135123 56.0652239,8.40207131 55.7650408,7.62994336 C55.4648576,6.85781542 54.5955777,6.4752286 53.8234497,6.77541179 C53.8184808,6.77734338 53.8184808,6.77734338 53.8135101,6.77927482 C53.0413181,7.07929302 52.6585455,7.94849117 52.9585637,8.72068323 C53.2585819,9.4928753 54.12778,9.87564785 54.8999721,9.57562965 L54.8999721,9.57562965 Z" id="Shape"></path>
+ <path d="M1.45327704,26.6978168 C1.54647464,26.6867112 1.63432439,26.660866 1.7147722,26.6228911 C2.03520341,26.4716332 2.23820252,26.1279362 2.1939679,25.7567213 C2.13862768,25.2923089 1.71728488,24.9606903 1.2528724,25.0160305 C1.24980572,25.0163959 1.24980572,25.0163959 1.24674021,25.0167611 C0.782326598,25.0720918 0.450699376,25.4934278 0.506030077,25.9578415 C0.561360778,26.4222551 0.982696791,26.7538823 1.4471104,26.6985516 C1.45019313,26.6981843 1.45019313,26.6981843 1.45327704,26.6978168 Z M9.34858965,26.1274206 C9.35409106,26.1266859 9.35409106,26.1266859 9.35959333,26.1259509 C10.1807278,26.0162709 10.7574756,25.2616967 10.6477955,24.4405622 C10.5381155,23.6194278 9.78354128,23.04268 8.96240683,23.15236 C8.95693539,23.1530908 8.95693539,23.1530908 8.95146479,23.1538215 C8.13032806,23.2634845 7.55356464,24.0180467 7.66322765,24.8391835 C7.77289065,25.6603202 8.52745292,26.2370836 9.34858965,26.1274206 L9.34858965,26.1274206 Z M17.0066591,25.0462427 C17.0121188,25.0454283 17.0121188,25.0454283 17.0175789,25.0446136 C17.8369369,24.9223683 18.4020584,24.1590479 18.279813,23.3396899 C18.1575677,22.5203319 17.3942473,21.9552104 16.5748893,22.0774558 C16.5694641,22.0782652 16.5694641,22.0782652 16.5640392,22.0790744 C15.7446783,22.2013005 15.1795389,22.9646076 15.301765,23.7839685 C15.4239911,24.6033294 16.1872982,25.1684688 17.0066591,25.0462427 L17.0066591,25.0462427 Z M24.8225082,24.4201748 C24.8297684,24.4189565 24.8297684,24.4189565 24.8370287,24.4177379 C25.922252,24.2355961 26.6543441,23.2081937 26.4722023,22.1229704 C26.2900605,21.0377471 25.2626581,20.3056549 24.1774348,20.4877968 C24.1702314,20.4890057 24.1702314,20.4890057 24.1630282,20.4902145 C23.0777996,20.6723249 22.3456777,21.6997061 22.5277881,22.7849347 C22.7098984,23.8701632 23.7372796,24.6022852 24.8225082,24.4201748 L24.8225082,24.4201748 Z M32.4725265,23.0495399 C33.5532108,22.8422598 34.2612448,21.7981584 34.0539647,20.7174741 C33.8466846,19.6367898 32.8025831,18.9287558 31.7218988,19.1360359 C31.714724,19.137412 31.714724,19.137412 31.7075489,19.138788 C30.6268567,19.3460265 29.9187826,20.3901008 30.1260211,21.470793 C30.3332597,22.5514853 31.3773339,23.2595594 32.4580262,23.0523208 C32.4652764,23.0509305 32.4652764,23.0509305 32.4725265,23.0495399 Z M39.8723866,20.8947688 C39.877909,20.8935242 39.877909,20.8935242 39.883431,20.8922795 C40.6915794,20.7101047 41.1990314,19.9072892 41.0168566,19.0991407 C40.8346818,18.2909923 40.0318663,17.7835404 39.2237179,17.9657152 C39.218279,17.9669412 39.218279,17.9669412 39.2128397,17.968167 C38.404681,18.1502959 37.8971834,18.9530826 38.0793123,19.7612414 C38.2614411,20.5694001 39.0642279,21.0768976 39.8723866,20.8947688 L39.8723866,20.8947688 Z M47.4276119,19.0082845 C47.4329844,19.0067855 47.4329844,19.0067855 47.4383562,19.0052864 C48.2362896,18.7825897 48.7026111,17.9552056 48.4799145,17.1572722 C48.2572179,16.3593388 47.4298337,15.8930173 46.6319003,16.1157139 C46.6266645,16.1171751 46.6266645,16.1171751 46.6214279,16.1186362 C45.8234736,16.3412577 45.3570742,17.168598 45.5796958,17.9665523 C45.8023173,18.7645067 46.6296576,19.230906 47.4276119,19.0082845 L47.4276119,19.0082845 Z M54.4138099,15.7087505 C54.4167849,15.7075945 54.4167849,15.7075945 54.419759,15.7064383 C54.8556933,15.5369585 55.0716973,15.0461733 54.9022174,14.610239 C54.7327376,14.1743047 54.2419524,13.9583007 53.8060181,14.1277806 C53.8032127,14.1288712 53.8032127,14.1288712 53.8004064,14.1299616 C53.3644359,14.2993484 53.148327,14.7900873 53.3177137,15.2260578 C53.4871005,15.6620283 53.9778394,15.8781372 54.4138099,15.7087505 L54.4138099,15.7087505 Z" id="Shape"></path>
+ </g>
+ <g id="top">
+ <path d="M1.4471104,12.2885536 C1.45019313,12.2881864 1.45019313,12.2881864 1.45327704,12.2878189 C1.91768952,12.2324787 2.24930811,11.8111359 2.1939679,11.3467234 C2.13862768,10.8823109 1.71728488,10.5506923 1.2528724,10.6060325 C1.24980572,10.606398 1.24980572,10.606398 1.24674021,10.6067632 C0.782326598,10.6620939 0.450699376,11.0834299 0.506030077,11.5478435 C0.561360778,12.0122571 0.982696791,12.3438844 1.4471104,12.2885536 L1.4471104,12.2885536 Z M9.34858965,12.1304907 C9.35409106,12.129756 9.35409106,12.129756 9.35959333,12.129021 C10.1807278,12.019341 10.7574756,11.2647668 10.6477955,10.4436323 C10.5381155,9.62249789 9.78354128,9.04575011 8.96240683,9.15543014 C8.95693539,9.15616095 8.95693539,9.15616095 8.95146479,9.15689157 C8.13032806,9.26655457 7.55356464,10.0211168 7.66322765,10.8422536 C7.77289065,11.6633903 8.52745292,12.2401537 9.34858965,12.1304907 L9.34858965,12.1304907 Z M17.0066591,11.0493128 C17.0121188,11.0484984 17.0121188,11.0484984 17.0175789,11.0476838 C17.8369369,10.9254384 18.4020584,10.1621181 18.279813,9.34276003 C18.1575677,8.52340201 17.3942473,7.95828052 16.5748893,8.08052587 C16.5694641,8.08133528 16.5694641,8.08133528 16.5640392,8.08214454 C15.7446783,8.20437064 15.1795389,8.96767771 15.301765,9.78703861 C15.4239911,10.6063995 16.1872982,11.1715389 17.0066591,11.0493128 L17.0066591,11.0493128 Z M24.8225082,10.4232459 C24.8297684,10.4220275 24.8297684,10.4220275 24.8370287,10.420809 C25.922252,10.2386672 26.6543441,9.21126476 26.4722023,8.12604147 C26.2900605,7.04081818 25.2626581,6.30872601 24.1774348,6.49086783 C24.1702314,6.4920768 24.1702314,6.4920768 24.1630282,6.49328559 C23.0777996,6.67539597 22.3456777,7.70277717 22.5277881,8.78800574 C22.7098984,9.87323431 23.7372796,10.6053563 24.8225082,10.4232459 L24.8225082,10.4232459 Z M32.4725265,9.05261002 C33.5532108,8.84532993 34.2612448,7.80122849 34.0539647,6.72054419 C33.8466846,5.63985989 32.8025831,4.93182589 31.7218988,5.13910599 C31.714724,5.14048211 31.714724,5.14048211 31.7075489,5.14185807 C30.6268567,5.34909665 29.9187826,6.39317088 30.1260211,7.47386314 C30.3332597,8.5545554 31.3773339,9.26262952 32.4580262,9.05539095 C32.4652764,9.05400057 32.4652764,9.05400057 32.4725265,9.05261002 Z M39.8723866,6.89476879 C39.877909,6.8935242 39.877909,6.8935242 39.883431,6.89227947 C40.6915794,6.71010471 41.1990314,5.90728916 41.0168566,5.09914075 C40.8346818,4.29099233 40.0318663,3.78354042 39.2237179,3.96571517 C39.218279,3.96694116 39.218279,3.96694116 39.2128397,3.96816703 C38.404681,4.15029588 37.8971834,4.9530826 38.0793123,5.76124136 C38.2614411,6.56940012 39.0642279,7.07689764 39.8723866,6.89476879 L39.8723866,6.89476879 Z M47.4276119,5.00828445 C47.4329844,5.00678549 47.4329844,5.00678549 47.4383562,5.00528637 C48.2362896,4.78258973 48.7026111,3.95520561 48.4799145,3.15727221 C48.2572179,2.35933881 47.4298337,1.89301728 46.6319003,2.11571391 C46.6266645,2.1171751 46.6266645,2.1171751 46.6214279,2.11863616 C45.8234736,2.34125773 45.3570742,3.16859798 45.5796958,3.96655233 C45.8023173,4.76450667 46.6296576,5.23090603 47.4276119,5.00828445 L47.4276119,5.00828445 Z M54.419759,2.30643871 C54.8556933,2.13695884 55.0716973,1.6461737 54.9022174,1.21023941 C54.7327376,0.774305114 54.2419524,0.558301127 53.8060181,0.727780997 C53.8032127,0.728871549 53.8032127,0.728871549 53.8004064,0.729962021 C53.3644359,0.89934874 53.148327,1.39008772 53.3177137,1.82605822 C53.4871005,2.26202871 53.9778394,2.47813756 54.4138099,2.30875084 C54.4167849,2.30759485 54.4167849,2.30759485 54.419759,2.30643871 Z" id="Shape"></path>
+ <path d="M1.67760355,20.096503 C1.68306395,20.0958524 1.68306395,20.0958524 1.68852642,20.0952015 C2.51113381,19.9971782 3.09852524,19.2508595 3.00050189,18.4282521 C2.90247854,17.6056447 2.15615986,17.0182533 1.33355246,17.1162767 C1.3281205,17.1169239 1.3281205,17.1169239 1.3226906,17.1175709 C0.500081196,17.2155774 -0.0873255124,17.961884 0.0106809923,18.7844934 C0.108687497,19.6071028 0.854994145,20.1945095 1.67760355,20.096503 L1.67760355,20.096503 Z M9.34858965,19.1274206 C9.35409106,19.1266859 9.35409106,19.1266859 9.35959333,19.1259509 C10.1807278,19.0162709 10.7574756,18.2616967 10.6477955,17.4405622 C10.5381155,16.6194278 9.78354128,16.04268 8.96240683,16.15236 C8.95693539,16.1530908 8.95693539,16.1530908 8.95146479,16.1538215 C8.13032806,16.2634845 7.55356464,17.0180467 7.66322765,17.8391835 C7.77289065,18.6603202 8.52745292,19.2370836 9.34858965,19.1274206 L9.34858965,19.1274206 Z M17.1767435,18.6256231 C17.1839958,18.6245412 17.1839958,18.6245412 17.1912486,18.6234592 C18.27963,18.4610765 19.0303002,17.4471319 18.8679175,16.3587506 C18.7055348,15.2703693 17.6915903,14.519699 16.6032089,14.6820817 C16.5960024,14.6831569 16.5960024,14.6831569 16.5887964,14.6842319 C15.5004112,14.846589 14.7497172,15.8605159 14.9120743,16.948901 C15.0744314,18.0372862 16.0883584,18.7879802 17.1767435,18.6256231 L17.1767435,18.6256231 Z M24.8370287,17.4177379 C25.922252,17.2355961 26.6543441,16.2081937 26.4722023,15.1229704 C26.2900605,14.0377471 25.2626581,13.3056549 24.1774348,13.4877968 C24.1702314,13.4890057 24.1702314,13.4890057 24.1630282,13.4902145 C23.0777996,13.6723249 22.3456777,14.6997061 22.5277881,15.7849347 C22.7098984,16.8701632 23.7372796,17.6022852 24.8225082,17.4201748 C24.8297684,17.4189565 24.8297684,17.4189565 24.8370287,17.4177379 Z M32.4725265,16.061085 C33.5532108,15.853199 34.2612448,14.8060455 34.0539647,13.7222022 C33.8466846,12.6383589 32.8025831,11.9282552 31.7218988,12.1361412 C31.714724,12.1375214 31.714724,12.1375214 31.7075489,12.1389013 C30.6268567,12.3467457 29.9187826,13.3938719 30.1260211,14.4777232 C30.3332597,15.5615745 31.3773339,16.2717185 32.4580262,16.0638741 C32.4652764,16.0624797 32.4652764,16.0624797 32.4725265,16.061085 Z M40.0707225,14.4695476 C40.0780573,14.4678946 40.0780573,14.4678946 40.0853916,14.4662413 C41.158768,14.2242783 41.8327617,13.1579849 41.5907986,12.0846085 C41.3488355,11.011232 40.2825422,10.3372384 39.2091657,10.5792015 C39.2019419,10.5808298 39.2019419,10.5808298 39.1947175,10.582458 C38.1213273,10.8243601 37.447273,11.8906152 37.6891752,12.9640053 C37.9310773,14.0373955 38.9973324,14.7114498 40.0707225,14.4695476 L40.0707225,14.4695476 Z M47.4276119,12.0082845 C47.4329844,12.0067855 47.4329844,12.0067855 47.4383562,12.0052864 C48.2362896,11.7825897 48.7026111,10.9552056 48.4799145,10.1572722 C48.2572179,9.35933881 47.4298337,8.89301728 46.6319003,9.11571391 C46.6266645,9.1171751 46.6266645,9.1171751 46.6214279,9.11863616 C45.8234736,9.34125773 45.3570742,10.168598 45.5796958,10.9665523 C45.8023173,11.7645067 46.6296576,12.230906 47.4276119,12.0082845 L47.4276119,12.0082845 Z M54.8999721,9.57562965 C54.9052414,9.57358217 54.9052414,9.57358217 54.9105092,9.57153441 C55.6826371,9.27135123 56.0652239,8.40207131 55.7650408,7.62994336 C55.4648576,6.85781542 54.5955777,6.4752286 53.8234497,6.77541179 C53.8184808,6.77734338 53.8184808,6.77734338 53.8135101,6.77927482 C53.0413181,7.07929302 52.6585455,7.94849117 52.9585637,8.72068323 C53.2585819,9.4928753 54.12778,9.87564785 54.8999721,9.57562965 L54.8999721,9.57562965 Z" id="Shape"></path>
+ <path d="M1.45327704,26.6978168 C1.54647464,26.6867112 1.63432439,26.660866 1.7147722,26.6228911 C2.03520341,26.4716332 2.23820252,26.1279362 2.1939679,25.7567213 C2.13862768,25.2923089 1.71728488,24.9606903 1.2528724,25.0160305 C1.24980572,25.0163959 1.24980572,25.0163959 1.24674021,25.0167611 C0.782326598,25.0720918 0.450699376,25.4934278 0.506030077,25.9578415 C0.561360778,26.4222551 0.982696791,26.7538823 1.4471104,26.6985516 C1.45019313,26.6981843 1.45019313,26.6981843 1.45327704,26.6978168 Z M9.34858965,26.1274206 C9.35409106,26.1266859 9.35409106,26.1266859 9.35959333,26.1259509 C10.1807278,26.0162709 10.7574756,25.2616967 10.6477955,24.4405622 C10.5381155,23.6194278 9.78354128,23.04268 8.96240683,23.15236 C8.95693539,23.1530908 8.95693539,23.1530908 8.95146479,23.1538215 C8.13032806,23.2634845 7.55356464,24.0180467 7.66322765,24.8391835 C7.77289065,25.6603202 8.52745292,26.2370836 9.34858965,26.1274206 L9.34858965,26.1274206 Z M17.0066591,25.0462427 C17.0121188,25.0454283 17.0121188,25.0454283 17.0175789,25.0446136 C17.8369369,24.9223683 18.4020584,24.1590479 18.279813,23.3396899 C18.1575677,22.5203319 17.3942473,21.9552104 16.5748893,22.0774558 C16.5694641,22.0782652 16.5694641,22.0782652 16.5640392,22.0790744 C15.7446783,22.2013005 15.1795389,22.9646076 15.301765,23.7839685 C15.4239911,24.6033294 16.1872982,25.1684688 17.0066591,25.0462427 L17.0066591,25.0462427 Z M24.8225082,24.4201748 C24.8297684,24.4189565 24.8297684,24.4189565 24.8370287,24.4177379 C25.922252,24.2355961 26.6543441,23.2081937 26.4722023,22.1229704 C26.2900605,21.0377471 25.2626581,20.3056549 24.1774348,20.4877968 C24.1702314,20.4890057 24.1702314,20.4890057 24.1630282,20.4902145 C23.0777996,20.6723249 22.3456777,21.6997061 22.5277881,22.7849347 C22.7098984,23.8701632 23.7372796,24.6022852 24.8225082,24.4201748 L24.8225082,24.4201748 Z M32.4725265,23.0495399 C33.5532108,22.8422598 34.2612448,21.7981584 34.0539647,20.7174741 C33.8466846,19.6367898 32.8025831,18.9287558 31.7218988,19.1360359 C31.714724,19.137412 31.714724,19.137412 31.7075489,19.138788 C30.6268567,19.3460265 29.9187826,20.3901008 30.1260211,21.470793 C30.3332597,22.5514853 31.3773339,23.2595594 32.4580262,23.0523208 C32.4652764,23.0509305 32.4652764,23.0509305 32.4725265,23.0495399 Z M39.8723866,20.8947688 C39.877909,20.8935242 39.877909,20.8935242 39.883431,20.8922795 C40.6915794,20.7101047 41.1990314,19.9072892 41.0168566,19.0991407 C40.8346818,18.2909923 40.0318663,17.7835404 39.2237179,17.9657152 C39.218279,17.9669412 39.218279,17.9669412 39.2128397,17.968167 C38.404681,18.1502959 37.8971834,18.9530826 38.0793123,19.7612414 C38.2614411,20.5694001 39.0642279,21.0768976 39.8723866,20.8947688 L39.8723866,20.8947688 Z M47.4276119,19.0082845 C47.4329844,19.0067855 47.4329844,19.0067855 47.4383562,19.0052864 C48.2362896,18.7825897 48.7026111,17.9552056 48.4799145,17.1572722 C48.2572179,16.3593388 47.4298337,15.8930173 46.6319003,16.1157139 C46.6266645,16.1171751 46.6266645,16.1171751 46.6214279,16.1186362 C45.8234736,16.3412577 45.3570742,17.168598 45.5796958,17.9665523 C45.8023173,18.7645067 46.6296576,19.230906 47.4276119,19.0082845 L47.4276119,19.0082845 Z M54.4138099,15.7087505 C54.4167849,15.7075945 54.4167849,15.7075945 54.419759,15.7064383 C54.8556933,15.5369585 55.0716973,15.0461733 54.9022174,14.610239 C54.7327376,14.1743047 54.2419524,13.9583007 53.8060181,14.1277806 C53.8032127,14.1288712 53.8032127,14.1288712 53.8004064,14.1299616 C53.3644359,14.2993484 53.148327,14.7900873 53.3177137,15.2260578 C53.4871005,15.6620283 53.9778394,15.8781372 54.4138099,15.7087505 L54.4138099,15.7087505 Z" id="Shape"></path>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/docs/index.html b/docs/index.html
index f6278f0f8..7e9ed7717 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,3 +1,18 @@
---
-layout: index
+title: Dotty
+layout: main
+extraCSS:
+ - css/animate.css
+ - css/default.css
+extraJS:
+ - js/elasticlunr.min.js
+ - js/search.js
+ - js/scrollreveal.min.js
+ - js/index.js
---
+<div id="content">
+ {% include logo-page.html %}
+ {% include faq.html %}
+ {% include features.html %}
+ {% include getting-started.html %}
+</div>
diff --git a/docs/js/highlight.pack.js b/docs/js/highlight.pack.js
deleted file mode 100644
index ce3e795d1..000000000
--- a/docs/js/highlight.pack.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/*! highlight.js v9.7.0 | BSD3 License | git.io/hljslicense */
-!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return R(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||R(i))return i}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:"start"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value)+'"'}l+="<"+t(e)+w.map.call(e.attributes,r).join("")+">"}function u(e){l+="</"+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):E(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"===e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function l(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?"":y.classPrefix,i='<span class="'+a,o=t?"":C;return i+=e+'">',i+n+o}function p(){var e,t,r,a;if(!E.k)return n(B);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)a+=n(B.substr(t,r.index-t)),e=g(E,r),e?(M+=e[1],a+=h(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return a+n(B.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=""}function v(e){k+=e.cN?h(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?B+=n:(a.rE||a.eE||(B+=n),b(),a.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"<unnamed>")+'"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var w,E=i||N,L={},k="";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,"",!0)+k);var B="",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substr(O,I.index-O),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},a=r;return t.filter(R).forEach(function(n){var t=l(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&"\n"===e?"<br>":y.tabReplace?n.replace(/\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n,t,r,o,s,p=i(e);a(p)||(y.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");w.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||"").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="</span>",y={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},I={"&":"&amp;","<":"&lt;",">":"&gt;"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},s=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{b:"`",e:"`",eB:!0,eE:!0,sL:"javascript"}];r.c=s;var i=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(s)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:s.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[i,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/</,r:0,c:[{cN:"attr",b:e,r:0},{b:/=\s*/,r:0,c:[{cN:"string",endsParent:!0,v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s"'=<>`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("<!--","-->",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{name:"style"},c:[t],starts:{e:"</style>",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{name:"script"},c:[t],starts:{e:"</script>",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("cs",function(e){var i={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double else enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while nameof add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",literal:"null false true"},r={cN:"string",b:'@"',e:'"',c:[{b:'""'}]},t=e.inherit(r,{i:/\n/}),a={cN:"subst",b:"{",e:"}",k:i},n=e.inherit(a,{i:/\n/}),c={cN:"string",b:/\$"/,e:'"',i:/\n/,c:[{b:"{{"},{b:"}}"},e.BE,n]},s={cN:"string",b:/\$@"/,e:'"',c:[{b:"{{"},{b:"}}"},{b:'""'},a]},o=e.inherit(s,{i:/\n/,c:[{b:"{{"},{b:"}}"},{b:'""'},n]});a.c=[s,c,r,e.ASM,e.QSM,e.CNM,e.CBCM],n.c=[o,c,t,e.ASM,e.QSM,e.CNM,e.inherit(e.CBCM,{i:/\n/})];var l={v:[s,c,r,e.ASM,e.QSM]},b=e.IR+"(<"+e.IR+"(\\s*,\\s*"+e.IR+")*>)?(\\[\\])?";return{aliases:["csharp"],k:i,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:"<!--|-->"},{b:"</?",e:">"}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},l,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{bK:"new return throw await",r:0},{cN:"function",b:"("+b+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:i,r:0,c:[l,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+")\\s*",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",w="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",u=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+w+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(u).concat(d)}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:"</?",e:">"},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],o=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=o,s.c=o,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:o}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,t,a]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},t,a]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[t.BE]},{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:"<",e:">",i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"</",c:n.concat([i,{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e]},t.CLCM,t.CBCM,i]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"section",b:/^[\w]+:\s*$/},{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},_={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},i=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:_,l:i,i:"</",c:[t,e.CLCM,e.CBCM,e.CNM,e.QSM,{cN:"string",v:[{b:'@"',e:'"',i:"\\n",c:[e.BE]},{b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"}]},{cN:"meta",b:"#",e:"$",c:[{cN:"meta-string",v:[{b:'"',e:'"'},{b:"<",e:">"}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:i,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("python",function(e){var r={cN:"meta",b:/^(>>>|\.\.\.) /},b={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]},a={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},l={cN:"params",b:/\(/,e:/\)/,c:["self",r,a,b]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[r,a,b,e.HCM,{v:[{cN:"function",bK:"def",r:10},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,l,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("java",function(e){var t=e.UIR+"(<"+e.UIR+"(\\s*,\\s*"+e.UIR+")*>)?",a="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports",r="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",s={cN:"number",b:r,r:0};return{aliases:["jsp"],k:a,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:a,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:a,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},s,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\._]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b:/</,e:/(\/\w+|\w+\/)>/,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("scala",function(e){var t={cN:"meta",b:"@[A-Za-z]+"},a={cN:"subst",v:[{b:"\\$[A-Za-z0-9_]+"},{b:"\\${",e:"}"}]},r={cN:"string",v:[{b:'"',e:'"',i:"\\n",c:[e.BE]},{b:'"""',e:'"""',r:10},{b:'[a-z]+"',e:'"',i:"\\n",c:[e.BE,a]},{cN:"string",b:'[a-z]+"""',e:'"""',c:[a],r:10}]},c={cN:"symbol",b:"'\\w[\\w\\d_]*(?!')"},i={cN:"type",b:"\\b[A-Z][A-Za-z0-9_]*",r:0},s={cN:"title",b:/[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,r:0},n={cN:"class",bK:"class object trait type",e:/[:={\[\n;]/,eE:!0,c:[{bK:"extends with",r:10},{b:/\[/,e:/\]/,eB:!0,eE:!0,r:0,c:[i]},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,r:0,c:[i]},s]},l={cN:"function",bK:"def",e:/[:={\[(\n;]/,eE:!0,c:[s]};return{k:{literal:"true false null",keyword:"type yield lazy override def with val var sealed abstract private trait object if forSome for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit"},c:[e.CLCM,e.CBCM,r,c,i,l,n,e.CNM,t]}}); \ No newline at end of file
diff --git a/docs/js/scrollreveal.min.js b/docs/js/scrollreveal.min.js
new file mode 100755
index 000000000..58c43dd2e
--- /dev/null
+++ b/docs/js/scrollreveal.min.js
@@ -0,0 +1 @@
+!function(){"use strict";function e(n){return"undefined"==typeof this||Object.getPrototypeOf(this)!==e.prototype?new e(n):(O=this,O.version="3.3.2",O.tools=new E,O.isSupported()?(O.tools.extend(O.defaults,n||{}),O.defaults.container=t(O.defaults),O.store={elements:{},containers:[]},O.sequences={},O.history=[],O.uid=0,O.initialized=!1):"undefined"!=typeof console&&null!==console,O)}function t(e){if(e&&e.container){if("string"==typeof e.container)return window.document.documentElement.querySelector(e.container);if(O.tools.isNode(e.container))return e.container}return O.defaults.container}function n(e,t){return"string"==typeof e?Array.prototype.slice.call(t.querySelectorAll(e)):O.tools.isNode(e)?[e]:O.tools.isNodeList(e)?Array.prototype.slice.call(e):[]}function i(){return++O.uid}function o(e,t,n){t.container&&(t.container=n),e.config?e.config=O.tools.extendClone(e.config,t):e.config=O.tools.extendClone(O.defaults,t),"top"===e.config.origin||"bottom"===e.config.origin?e.config.axis="Y":e.config.axis="X"}function r(e){var t=window.getComputedStyle(e.domEl);e.styles||(e.styles={transition:{},transform:{},computed:{}},e.styles.inline=e.domEl.getAttribute("style")||"",e.styles.inline+="; visibility: visible; ",e.styles.computed.opacity=t.opacity,t.transition&&"all 0s ease 0s"!==t.transition?e.styles.computed.transition=t.transition+", ":e.styles.computed.transition=""),e.styles.transition.instant=s(e,0),e.styles.transition.delayed=s(e,e.config.delay),e.styles.transform.initial=" -webkit-transform:",e.styles.transform.target=" -webkit-transform:",a(e),e.styles.transform.initial+="transform:",e.styles.transform.target+="transform:",a(e)}function s(e,t){var n=e.config;return"-webkit-transition: "+e.styles.computed.transition+"-webkit-transform "+n.duration/1e3+"s "+n.easing+" "+t/1e3+"s, opacity "+n.duration/1e3+"s "+n.easing+" "+t/1e3+"s; transition: "+e.styles.computed.transition+"transform "+n.duration/1e3+"s "+n.easing+" "+t/1e3+"s, opacity "+n.duration/1e3+"s "+n.easing+" "+t/1e3+"s; "}function a(e){var t,n=e.config,i=e.styles.transform;t="top"===n.origin||"left"===n.origin?/^-/.test(n.distance)?n.distance.substr(1):"-"+n.distance:n.distance,parseInt(n.distance)&&(i.initial+=" translate"+n.axis+"("+t+")",i.target+=" translate"+n.axis+"(0)"),n.scale&&(i.initial+=" scale("+n.scale+")",i.target+=" scale(1)"),n.rotate.x&&(i.initial+=" rotateX("+n.rotate.x+"deg)",i.target+=" rotateX(0)"),n.rotate.y&&(i.initial+=" rotateY("+n.rotate.y+"deg)",i.target+=" rotateY(0)"),n.rotate.z&&(i.initial+=" rotateZ("+n.rotate.z+"deg)",i.target+=" rotateZ(0)"),i.initial+="; opacity: "+n.opacity+";",i.target+="; opacity: "+e.styles.computed.opacity+";"}function l(e){var t=e.config.container;t&&O.store.containers.indexOf(t)===-1&&O.store.containers.push(e.config.container),O.store.elements[e.id]=e}function c(e,t,n){var i={target:e,config:t,interval:n};O.history.push(i)}function f(){if(O.isSupported()){y();for(var e=0;e<O.store.containers.length;e++)O.store.containers[e].addEventListener("scroll",d),O.store.containers[e].addEventListener("resize",d);O.initialized||(window.addEventListener("scroll",d),window.addEventListener("resize",d),O.initialized=!0)}return O}function d(){T(y)}function u(){var e,t,n,i;O.tools.forOwn(O.sequences,function(o){i=O.sequences[o],e=!1;for(var r=0;r<i.elemIds.length;r++)n=i.elemIds[r],t=O.store.elements[n],q(t)&&!e&&(e=!0);i.active=e})}function y(){var e,t;u(),O.tools.forOwn(O.store.elements,function(n){t=O.store.elements[n],e=w(t),g(t)?(t.config.beforeReveal(t.domEl),e?t.domEl.setAttribute("style",t.styles.inline+t.styles.transform.target+t.styles.transition.delayed):t.domEl.setAttribute("style",t.styles.inline+t.styles.transform.target+t.styles.transition.instant),p("reveal",t,e),t.revealing=!0,t.seen=!0,t.sequence&&m(t,e)):v(t)&&(t.config.beforeReset(t.domEl),t.domEl.setAttribute("style",t.styles.inline+t.styles.transform.initial+t.styles.transition.instant),p("reset",t),t.revealing=!1)})}function m(e,t){var n=0,i=0,o=O.sequences[e.sequence.id];o.blocked=!0,t&&"onload"===e.config.useDelay&&(i=e.config.delay),e.sequence.timer&&(n=Math.abs(e.sequence.timer.started-new Date),window.clearTimeout(e.sequence.timer)),e.sequence.timer={started:new Date},e.sequence.timer.clock=window.setTimeout(function(){o.blocked=!1,e.sequence.timer=null,d()},Math.abs(o.interval)+i-n)}function p(e,t,n){var i=0,o=0,r="after";switch(e){case"reveal":o=t.config.duration,n&&(o+=t.config.delay),r+="Reveal";break;case"reset":o=t.config.duration,r+="Reset"}t.timer&&(i=Math.abs(t.timer.started-new Date),window.clearTimeout(t.timer.clock)),t.timer={started:new Date},t.timer.clock=window.setTimeout(function(){t.config[r](t.domEl),t.timer=null},o-i)}function g(e){if(e.sequence){var t=O.sequences[e.sequence.id];return t.active&&!t.blocked&&!e.revealing&&!e.disabled}return q(e)&&!e.revealing&&!e.disabled}function w(e){var t=e.config.useDelay;return"always"===t||"onload"===t&&!O.initialized||"once"===t&&!e.seen}function v(e){if(e.sequence){var t=O.sequences[e.sequence.id];return!t.active&&e.config.reset&&e.revealing&&!e.disabled}return!q(e)&&e.config.reset&&e.revealing&&!e.disabled}function b(e){return{width:e.clientWidth,height:e.clientHeight}}function h(e){if(e&&e!==window.document.documentElement){var t=x(e);return{x:e.scrollLeft+t.left,y:e.scrollTop+t.top}}return{x:window.pageXOffset,y:window.pageYOffset}}function x(e){var t=0,n=0,i=e.offsetHeight,o=e.offsetWidth;do isNaN(e.offsetTop)||(t+=e.offsetTop),isNaN(e.offsetLeft)||(n+=e.offsetLeft),e=e.offsetParent;while(e);return{top:t,left:n,height:i,width:o}}function q(e){function t(){var t=c+a*s,n=f+l*s,i=d-a*s,y=u-l*s,m=r.y+e.config.viewOffset.top,p=r.x+e.config.viewOffset.left,g=r.y-e.config.viewOffset.bottom+o.height,w=r.x-e.config.viewOffset.right+o.width;return t<g&&i>m&&n>p&&y<w}function n(){return"fixed"===window.getComputedStyle(e.domEl).position}var i=x(e.domEl),o=b(e.config.container),r=h(e.config.container),s=e.config.viewFactor,a=i.height,l=i.width,c=i.top,f=i.left,d=c+a,u=f+l;return t()||n()}function E(){}var O,T;e.prototype.defaults={origin:"bottom",distance:"20px",duration:500,delay:0,rotate:{x:0,y:0,z:0},opacity:0,scale:.9,easing:"cubic-bezier(0.6, 0.2, 0.1, 1)",container:window.document.documentElement,mobile:!0,reset:!1,useDelay:"always",viewFactor:.2,viewOffset:{top:0,right:0,bottom:0,left:0},beforeReveal:function(e){},beforeReset:function(e){},afterReveal:function(e){},afterReset:function(e){}},e.prototype.isSupported=function(){var e=document.documentElement.style;return"WebkitTransition"in e&&"WebkitTransform"in e||"transition"in e&&"transform"in e},e.prototype.reveal=function(e,s,a,d){var u,y,m,p,g,w;if(void 0!==s&&"number"==typeof s?(a=s,s={}):void 0!==s&&null!==s||(s={}),u=t(s),y=n(e,u),!y.length)return O;a&&"number"==typeof a&&(w=i(),g=O.sequences[w]={id:w,interval:a,elemIds:[],active:!1});for(var v=0;v<y.length;v++)p=y[v].getAttribute("data-sr-id"),p?m=O.store.elements[p]:(m={id:i(),domEl:y[v],seen:!1,revealing:!1},m.domEl.setAttribute("data-sr-id",m.id)),g&&(m.sequence={id:g.id,index:g.elemIds.length},g.elemIds.push(m.id)),o(m,s,u),r(m),l(m),O.tools.isMobile()&&!m.config.mobile||!O.isSupported()?(m.domEl.setAttribute("style",m.styles.inline),m.disabled=!0):m.revealing||m.domEl.setAttribute("style",m.styles.inline+m.styles.transform.initial);return!d&&O.isSupported()&&(c(e,s,a),O.initTimeout&&window.clearTimeout(O.initTimeout),O.initTimeout=window.setTimeout(f,0)),O},e.prototype.sync=function(){if(O.history.length&&O.isSupported()){for(var e=0;e<O.history.length;e++){var t=O.history[e];O.reveal(t.target,t.config,t.interval,!0)}f()}return O},E.prototype.isObject=function(e){return null!==e&&"object"==typeof e&&e.constructor===Object},E.prototype.isNode=function(e){return"object"==typeof window.Node?e instanceof window.Node:e&&"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},E.prototype.isNodeList=function(e){var t=Object.prototype.toString.call(e),n=/^\[object (HTMLCollection|NodeList|Object)\]$/;return"object"==typeof window.NodeList?e instanceof window.NodeList:e&&"object"==typeof e&&n.test(t)&&"number"==typeof e.length&&(0===e.length||this.isNode(e[0]))},E.prototype.forOwn=function(e,t){if(!this.isObject(e))throw new TypeError('Expected "object", but received "'+typeof e+'".');for(var n in e)e.hasOwnProperty(n)&&t(n)},E.prototype.extend=function(e,t){return this.forOwn(t,function(n){this.isObject(t[n])?(e[n]&&this.isObject(e[n])||(e[n]={}),this.extend(e[n],t[n])):e[n]=t[n]}.bind(this)),e},E.prototype.extendClone=function(e,t){return this.extend(this.extend({},e),t)},E.prototype.isMobile=function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},T=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)},"function"==typeof define&&"object"==typeof define.amd&&define.amd?define(function(){return e}):"undefined"!=typeof module&&module.exports?module.exports=e:window.ScrollReveal=e}(); \ No newline at end of file
diff --git a/docs/search.html b/docs/search.html
deleted file mode 100644
index 20cccc11f..000000000
--- a/docs/search.html
+++ /dev/null
@@ -1,35 +0,0 @@
----
-layout: search
-title: "Search"
----
-<h1 id="search">Search Results</h1>
-
-<form id="search-bar" action="/search.html" method="get">
- <input placeholder="Search" type="text" id="search-box" name="query">
-</form>
-
-<ul id="search-results"></ul>
-
-<script>
- window.store = {
- {% for post in site.posts %}
- "{{ post.url | slugify }}": {
- "title": "{{ post.title | xml_escape }}",
- "author": "{{ post.author | xml_escape }}",
- "content": {{ post.content | markdownify | strip_html | lstrip | jsonify }},
- "url": "{{ post.url | xml_escape }}"
- },
- {% endfor %}
- {% for page in site.html_pages %}
- "{{ page.url | slugify }}": {
- "title": "{{ page.title | xml_escape }}",
- "name": "{{ page.name | xml_escape }}",
- "content": {{ page.content | markdownify | strip_html | lstrip | jsonify }},
- "url": "{{ page.url | xml_escape }}"
- }
- {% unless forloop.last %},{% endunless %}
- {% endfor %}
- };
-</script>
-<script src="/js/elasticlunr.min.js"></script>
-<script src="/js/search.js"></script>
diff --git a/docs/sidebar.yml b/docs/sidebar.yml
new file mode 100644
index 000000000..7ffa1f5b7
--- /dev/null
+++ b/docs/sidebar.yml
@@ -0,0 +1,49 @@
+sidebar:
+ - title: Blog
+ url: blog/index.html
+ - title: Docs
+ url: docs/index.html
+ - title: Usage
+ subsection:
+ - title: cbt-projects
+ url: docs/usage/cbt-projects.html
+ - title: sbt-projects
+ url: docs/usage/sbt-projects.html
+ - title: Dottydoc
+ url: docs/usage/dottydoc.html
+ - title: Migrating
+ url: docs/usage/migrating.html
+ - title: Contributing
+ subsection:
+ - title: Eclipse
+ url: docs/contributing/eclipse.html
+ - title: Getting Started
+ url: docs/contributing/getting-started.html
+ - title: IntelliJ IDEA
+ url: docs/contributing/intellij-idea.html
+ - title: Workflow
+ url: docs/contributing/workflow.html
+ - title: Internals
+ subsection:
+ - title: Backend
+ url: docs/internals/backend.html
+ - title: Benchmarks
+ url: docs/internals/benchmarks.html
+ - title: Classpaths
+ url: docs/internals/classpaths.html
+ - title: Core Data Structrues
+ url: docs/internals/core-data-structures.html
+ - title: Contexts
+ url: docs/internals/contexts.html
+ - title: Dotc vs Scalac
+ url: docs/internals/dotc-scalac.html
+ - title: Higher-Kinded Types
+ url: docs/internals/higher-kinded-v2.html
+ - title: Overall Structure
+ url: docs/internals/overall-structure.html
+ - title: Periods
+ url: docs/internals/periods.html
+ - title: Syntax
+ url: docs/internals/syntax.html
+ - title: Type System
+ url: docs/internals/type-system.html
diff --git a/library/src/scala/Selectable.scala b/library/src/scala/Selectable.scala
new file mode 100644
index 000000000..c5c714ca9
--- /dev/null
+++ b/library/src/scala/Selectable.scala
@@ -0,0 +1,8 @@
+package scala
+import scala.reflect.ClassTag
+
+trait Selectable extends Any {
+ def selectDynamic(name: String): Any
+ def selectDynamicMethod(name: String, paramClasses: ClassTag[_]*): Any =
+ new UnsupportedOperationException("selectDynamicMethod")
+}
diff --git a/library/src/scala/reflect/Selectable.scala b/library/src/scala/reflect/Selectable.scala
new file mode 100644
index 000000000..0dbdbc293
--- /dev/null
+++ b/library/src/scala/reflect/Selectable.scala
@@ -0,0 +1,73 @@
+package scala.reflect
+
+class Selectable(val receiver: Any) extends AnyVal with scala.Selectable {
+ def selectDynamic(name: String): Any = {
+ val rcls = receiver.getClass
+ try {
+ val fld = rcls.getField(name)
+ fld.get(receiver)
+ }
+ catch {
+ case ex: NoSuchFieldError =>
+ selectDynamicMethod(name).asInstanceOf[() => Any]()
+ }
+ }
+
+ override def selectDynamicMethod(name: String, paramTypes: ClassTag[_]*): Any = {
+ val rcls = receiver.getClass
+ val paramClasses = paramTypes.map(_.runtimeClass)
+ val mth = rcls.getMethod(name, paramClasses: _*)
+ paramTypes.length match {
+ case 0 => () =>
+ mth.invoke(receiver)
+ case 1 => (x0: Any) =>
+ mth.invoke(receiver, x0.asInstanceOf[Object])
+ case 2 => (x0: Any, x1: Any) =>
+ mth.invoke(receiver,
+ x0.asInstanceOf[Object],
+ x1.asInstanceOf[Object])
+ case 3 => (x0: Any, x1: Any, x2: Any) =>
+ mth.invoke(receiver,
+ x0.asInstanceOf[Object],
+ x1.asInstanceOf[Object],
+ x2.asInstanceOf[Object])
+ case 4 => (x0: Any, x1: Any, x2: Any, x3: Any) =>
+ mth.invoke(receiver,
+ x0.asInstanceOf[Object],
+ x1.asInstanceOf[Object],
+ x2.asInstanceOf[Object],
+ x3.asInstanceOf[Object])
+ case 5 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any) =>
+ mth.invoke(receiver,
+ x0.asInstanceOf[Object],
+ x1.asInstanceOf[Object],
+ x2.asInstanceOf[Object],
+ x3.asInstanceOf[Object],
+ x4.asInstanceOf[Object])
+ case 6 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any, x5: Any) =>
+ mth.invoke(receiver,
+ x0.asInstanceOf[Object],
+ x1.asInstanceOf[Object],
+ x2.asInstanceOf[Object],
+ x3.asInstanceOf[Object],
+ x4.asInstanceOf[Object],
+ x5.asInstanceOf[Object])
+ case 7 => (x0: Any, x1: Any, x2: Any, x3: Any, x4: Any, x5: Any, x6: Any) =>
+ mth.invoke(receiver,
+ x0.asInstanceOf[Object],
+ x1.asInstanceOf[Object],
+ x2.asInstanceOf[Object],
+ x3.asInstanceOf[Object],
+ x4.asInstanceOf[Object],
+ x5.asInstanceOf[Object],
+ x6.asInstanceOf[Object])
+ }
+ }
+}
+
+object Selectable {
+ implicit def reflectiveSelectable(receiver: Any): scala.Selectable = receiver match {
+ case receiver: scala.Selectable => receiver
+ case _ => new Selectable(receiver)
+ }
+}
diff --git a/project/Build.scala b/project/Build.scala
index 778492624..a6505a12c 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -52,6 +52,15 @@ object DottyBuild extends Build {
lazy val dotr =
inputKey[Unit]("run compiled binary using the correct classpath, or the user supplied classpath")
+ // Compiles the documentation and static site
+ lazy val genDocs = inputKey[Unit]("run dottydoc to generate static documentation site")
+
+ /** Dottydoc deps */
+ lazy val dottydocDeps = SettingKey[Seq[ModuleID]](
+ "dottydocDeps",
+ "dottydoc dependencies, should be moved to a dottydoc sbt subproject eventually"
+ )
+
override def settings: Seq[Setting[_]] = {
super.settings ++ Seq(
scalaVersion in Global := scalacVersion,
@@ -177,16 +186,28 @@ object DottyBuild extends Build {
//http://stackoverflow.com/questions/10472840/how-to-attach-sources-to-sbt-managed-dependencies-in-scala-ide#answer-11683728
com.typesafe.sbteclipse.plugin.EclipsePlugin.EclipseKeys.withSource := true,
+ dottydocDeps := Seq(
+ "com.vladsch.flexmark" % "flexmark" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-gfm-tasklist" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-gfm-tables" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-autolink" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-anchorlink" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-emoji" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-gfm-strikethrough" % "0.11.1",
+ "com.vladsch.flexmark" % "flexmark-ext-yaml-front-matter" % "0.11.1",
+ "com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % "2.8.6",
+ "nl.big-o" % "liqp" % "0.6.7"
+ ),
+
// get libraries onboard
partestDeps := Seq(scalaCompiler,
"org.scala-lang" % "scala-reflect" % scalacVersion,
"org.scala-lang" % "scala-library" % scalacVersion % "test"),
libraryDependencies ++= partestDeps.value,
+ libraryDependencies ++= dottydocDeps.value,
libraryDependencies ++= Seq("org.scala-lang.modules" %% "scala-xml" % "1.0.1",
"org.scala-lang.modules" %% "scala-partest" % "1.0.11" % "test",
- dottyOrganization % "dottydoc-client" % "0.1.0",
"com.novocode" % "junit-interface" % "0.11" % "test",
- "com.github.spullara.mustache.java" % "compiler" % "0.9.3",
"com.typesafe.sbt" % "sbt-interface" % sbtVersion.value),
// enable improved incremental compilation algorithm
incOptions := incOptions.value.withNameHashing(true),
@@ -204,6 +225,21 @@ object DottyBuild extends Build {
)
}.evaluated,
+ genDocs := Def.inputTaskDyn {
+ val dottyLib = packageAll.value("dotty-library")
+ val dottyInterfaces = packageAll.value("dotty-interfaces")
+ val otherDeps = (dependencyClasspath in Compile).value.map(_.data).mkString(":")
+ val sources = (managedSources in (Compile, compile)).value ++ (unmanagedSources in (Compile, compile)).value
+ val args: Seq[String] = Seq(
+ "-siteroot", "docs",
+ "-project", "Dotty",
+ "-classpath", s"$dottyLib:$dottyInterfaces:$otherDeps"
+ )
+ (runMain in Compile).toTask(
+ s""" dotty.tools.dottydoc.Main ${args.mkString(" ")} ${sources.mkString(" ")}"""
+ )
+ }.evaluated,
+
// Override run to be able to run compiled classfiles
dotr := {
val args: Seq[String] = spaceDelimited("<arg>").parsed
@@ -369,6 +405,8 @@ object DottyBuild extends Build {
// project, for sbt integration
// FIXME: note part of dottyCompilerSettings because the doc-tool does not
// compile with dotty
+ unmanagedResourceDirectories in Compile := Seq((resourceDirectory in Compile).value),
+ unmanagedResourceDirectories in Compile += baseDirectory.value / ".." / "doc-tool" / "resources",
unmanagedSourceDirectories in Compile := Seq((scalaSource in Compile).value),
unmanagedSourceDirectories in Compile += baseDirectory.value / ".." / "doc-tool" / "src",
unmanagedSourceDirectories in Test := Seq((scalaSource in Test).value),
diff --git a/project/scripts/genDocs b/project/scripts/genDocs
new file mode 100755
index 000000000..d18a583be
--- /dev/null
+++ b/project/scripts/genDocs
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+# Usage: ./genDocs <test variable> <dotty-bot password>
+
+set -e
+# set extended glob, needed for rm everything but x
+shopt -s extglob
+
+if [ "$1" = "test" ]; then
+
+ # make sure that BOT_PASS is set
+ if [ -z ${2+x} ]; then
+ echo "BOT_PASS unset, unable to push without password" 1>&2
+ exit 1
+ else
+ BOT_PASS=$2
+ fi
+
+ echo "Working directory: $PWD"
+
+ # this command will generate docs in $PWD/docs/_site
+ sbt -J-Xmx4096m \
+ -J-XX:ReservedCodeCacheSize=512m \
+ -J-XX:MaxMetaspaceSize=1024m \
+ -Ddotty.drone.mem=4096m \
+ -ivy /var/cache/drone/ivy2 \
+ "genDocs"
+
+ # make sure that the previous command actually succeeded
+ if [ ! -d "$PWD/docs/_site" ]; then
+ echo "Output directory did not exist: $PWD/docs/_site" 1>&2
+ exit 1
+ fi
+
+ # save current head for commit message in gh-pages
+ GIT_HEAD=$(git rev-parse HEAD)
+
+ # check out correct branch
+ git fetch origin gh-pages:gh-pages
+ git checkout gh-pages
+
+ # move newly generated _site dir to $PWD
+ mv $PWD/docs/_site .
+
+ # remove everything BUT _site dir
+ rm -rf !(_site)
+
+ # copy new contents to $PWD
+ mv _site/* .
+
+ # remove now empty _site dir
+ rm -rf _site
+
+ # set github credentials
+ git config user.name "dotty-bot"
+ git config user.email "felix.mulder@epfl.ch"
+
+ # add all contents of $PWD to commit
+ git add -A
+ git commit -m "Update gh-pages site for $GIT_HEAD" || echo "nothing new to commit"
+
+ # push using dotty-bot to origin
+ git push https://dotty-bot:$BOT_PASS@github.com/lampepfl/dotty.git || echo "couldn't push, since nothing was added"
+else
+ # wrong parameter passed, should only generate docs if argument is "test"
+ # to avoid multiple site gens
+ echo "Not generating docs for $1"
+fi
diff --git a/sbt-bridge/src/xsbt/ScaladocInterface.scala b/sbt-bridge/src/xsbt/ScaladocInterface.scala
index 3ad9c7941..1eae8374d 100644
--- a/sbt-bridge/src/xsbt/ScaladocInterface.scala
+++ b/sbt-bridge/src/xsbt/ScaladocInterface.scala
@@ -3,8 +3,7 @@
*/
package xsbt
-import xsbti.Logger
-import dotty.tools.dottydoc.api.scala.Dottydoc
+import xsbti.{ Logger, Severity }
import java.net.URL
class ScaladocInterface {
@@ -12,22 +11,13 @@ class ScaladocInterface {
(new DottydocRunner(args, log, delegate)).run()
}
-class DottydocRunner(args: Array[String], log: Logger, delegate: xsbti.Reporter) extends Dottydoc {
- def run(): Unit = getOutputFolder(args).map { outputFolder =>
- val index = createIndex(args)
- val resources = getResources(args)
- val template = getTemplate(resources)
-
- template.fold(writeJson(index, outputFolder)) { tpl =>
- buildDocs(outputFolder, tpl, resources, index)
- }
- } getOrElse {
- delegate.log(
- NoPosition,
- "No output folder set for API documentation (\"-d\" parameter should be passed to the documentation tool)",
- xsbti.Severity.Error
- )
- }
+class DottydocRunner(args: Array[String], log: Logger, delegate: xsbti.Reporter) {
+ def run(): Unit = delegate.log(
+ NoPosition,
+ """|The dotty sbt-bridge currently does not support doc generation directly
+ |via sbt. Please see the dotty documentation at dotty.epfl.ch""".stripMargin,
+ Severity.Error
+ )
private[this] val NoPosition = new xsbti.Position {
val line = xsbti.Maybe.nothing[Integer]
diff --git a/tests/neg/i1568.scala b/tests/neg/i1568.scala
new file mode 100644
index 000000000..a260c530b
--- /dev/null
+++ b/tests/neg/i1568.scala
@@ -0,0 +1,3 @@
+object Test {
+ inline def foo(n: Int) = foo(n) // error: cyclic reference
+}
diff --git a/tests/neg/structural.scala b/tests/neg/structural.scala
new file mode 100644
index 000000000..aab52b2cb
--- /dev/null
+++ b/tests/neg/structural.scala
@@ -0,0 +1,11 @@
+object Test3 {
+ import scala.reflect.Selectable.reflectiveSelectable
+ def g(x: { type T ; def t: T ; def f(a: T): Boolean }) = x.f(x.t) // error: no ClassTag for x.T
+ g(new { type T = Int; def t = 4; def f(a:T) = true })
+ g(new { type T = Any; def t = 4; def f(a:T) = true })
+ val y: { type T = Int; def t = 4; def f(a:T) = true }
+ = new { type T = Int; def t = 4; def f(a:T) = true }
+
+ def h(x: { def f[T](a: T): Int }) = x.f[Int](4) // error: polymorphic refinement method ... no longer allowed
+
+}
diff --git a/tests/neg/valueclasses-impl-restrictions.scala b/tests/neg/valueclasses-impl-restrictions.scala
new file mode 100644
index 000000000..9f33b7e7c
--- /dev/null
+++ b/tests/neg/valueclasses-impl-restrictions.scala
@@ -0,0 +1,19 @@
+class X1(val s: String) extends AnyVal {
+ trait I2 { // error: value class may not define an inner class or trait
+ val q: String
+ def z = s + q
+ }
+}
+
+class X2(val s: String) extends AnyVal {
+ private[this] class I2(val q: String) // error: value class may not define an inner class or trait
+
+ def y(i: Int) = {
+ val i2 = new I2(i.toString)
+ i2.q + s
+ }
+}
+
+class X3(val s: String) extends AnyVal {
+ object I3 // error: value class may not define non-parameter field
+}
diff --git a/tests/neg/zoo.scala b/tests/neg/zoo.scala
index 19efcc1d7..1674548e8 100644
--- a/tests/neg/zoo.scala
+++ b/tests/neg/zoo.scala
@@ -7,19 +7,19 @@ type Grass = {
}
type Animal = {
type Food
- def eats(food: Food): Unit // error
- def gets: Food // error
+ def eats(food: Food): Unit
+ def gets: Food
}
type Cow = {
type IsMeat = Any
type Food <: Grass
- def eats(food: Grass): Unit // error
- def gets: Grass // error
+ def eats(food: Grass): Unit
+ def gets: Grass
}
type Lion = {
type Food = Meat
- def eats(food: Meat): Unit // error
- def gets: Meat // error
+ def eats(food: Meat): Unit
+ def gets: Meat
}
def newMeat: Meat = new {
type IsMeat = Any
@@ -40,5 +40,5 @@ def newLion: Lion = new {
}
val milka = newCow
val leo = newLion
-leo.eats(milka) // structural select not supported
+leo.eats(milka) // error: no projector found
}
diff --git a/tests/pos/backquoted_type_operator.scala b/tests/pos/backquoted_type_operator.scala
new file mode 100644
index 000000000..5ee875702
--- /dev/null
+++ b/tests/pos/backquoted_type_operator.scala
@@ -0,0 +1,4 @@
+object Test {
+ type `&`[L,R] = L
+ val x: Int `&` String = 10
+}
diff --git a/tests/pos/f-bounded-case-class.scala b/tests/pos/f-bounded-case-class.scala
new file mode 100644
index 000000000..82b8758b2
--- /dev/null
+++ b/tests/pos/f-bounded-case-class.scala
@@ -0,0 +1 @@
+case class Test[X <: List[Y], Y <: List[X]](x: X, y: Y)
diff --git a/tests/pos/i1723.scala b/tests/pos/i1723.scala
new file mode 100644
index 000000000..75f7cd95c
--- /dev/null
+++ b/tests/pos/i1723.scala
@@ -0,0 +1,8 @@
+class A {
+ private val x: List[Int] = List(1)
+ def foo = x.head // foo inferred type is this.x.scala$collection$immutable$List$$A
+}
+
+class B extends A {
+ foo
+}
diff --git a/tests/pos/i1866.scala b/tests/pos/i1866.scala
new file mode 100644
index 000000000..918d2e182
--- /dev/null
+++ b/tests/pos/i1866.scala
@@ -0,0 +1,5 @@
+import scala.reflect.Selectable.reflectiveSelectable
+object Test {
+ def f(g: { val update: Unit }) = g.update
+ def main(update: Array[String]) = {}
+}
diff --git a/tests/pos/zoo2.scala b/tests/pos/zoo2.scala
new file mode 100644
index 000000000..06210fe67
--- /dev/null
+++ b/tests/pos/zoo2.scala
@@ -0,0 +1,45 @@
+import scala.reflect.Selectable.reflectiveSelectable
+object Test {
+type Meat = {
+ type IsMeat = Any
+}
+type Grass = {
+ type IsGrass = Any
+}
+type Animal = {
+ type Food
+ def eats(food: Food): Unit
+ def gets: Food
+}
+type Cow = {
+ type IsMeat = Any
+ type Food <: Grass
+ def eats(food: Grass): Unit
+ def gets: Grass
+}
+type Lion = {
+ type Food = Meat
+ def eats(food: Meat): Unit
+ def gets: Meat
+}
+def newMeat: Meat = new {
+ type IsMeat = Any
+}
+def newGrass: Grass = new {
+ type IsGrass = Any
+}
+def newCow: Cow = new {
+ type IsMeat = Any
+ type Food = Grass
+ def eats(food: Grass) = ()
+ def gets = newGrass
+}
+def newLion: Lion = new {
+ type Food = Meat
+ def eats(food: Meat) = ()
+ def gets = newMeat
+}
+val milka = newCow
+val leo = newLion
+leo.eats(milka)
+}
diff --git a/tests/repl/errmsgs.check b/tests/repl/errmsgs.check
index f0ccdf53f..0dc8e8ae5 100644
--- a/tests/repl/errmsgs.check
+++ b/tests/repl/errmsgs.check
@@ -78,4 +78,11 @@ scala> class Foo() { def bar: Int = 1 }; val foo = new Foo(); foo.barr
4 |class Foo() { def bar: Int = 1 }; val foo = new Foo(); foo.barr
| ^^^^^^^^
| value `barr` is not a member of Foo(foo) - did you mean `foo.bar`?
+scala> val x: List[Int] = "foo" :: List(1)
+-- [E007] Type Mismatch Error: <console> ---------------------------------------
+4 |val x: List[Int] = "foo" :: List(1)
+ | ^^^^^
+ | found: String($1$)
+ | required: Int
+ |
scala> :quit
diff --git a/tests/pos/functionXXL.scala b/tests/run/functionXXL.scala
index 1063e4170..de8c8e3fa 100644
--- a/tests/pos/functionXXL.scala
+++ b/tests/run/functionXXL.scala
@@ -59,12 +59,12 @@ object Test {
- println(f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ assert(42 == f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26))
- println(g(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ assert(42 == g(1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26))
}
diff --git a/tests/run/i1569.check b/tests/run/i1569.check
new file mode 100644
index 000000000..0d55bed3a
--- /dev/null
+++ b/tests/run/i1569.check
@@ -0,0 +1,2 @@
+foo
+foo
diff --git a/tests/run/i1569.scala b/tests/run/i1569.scala
new file mode 100644
index 000000000..2c5dd4e5a
--- /dev/null
+++ b/tests/run/i1569.scala
@@ -0,0 +1,5 @@
+object Test {
+ inline def foo(inline n: => Int) = n + n
+
+ def main(args: Array[String]): Unit = foo({ println("foo"); 42 })
+}
diff --git a/tests/run/i1915.scala b/tests/run/i1915.scala
new file mode 100644
index 000000000..ee192f6fe
--- /dev/null
+++ b/tests/run/i1915.scala
@@ -0,0 +1,9 @@
+object Test {
+ def main(args: Array[String]) = {
+ assert(new IntFunction26().apply(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26) == 42)
+ }
+}
+
+class IntFunction26 extends Function26[Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int] {
+ def apply(x1: Int, x2: Int, x3: Int, x4: Int, x5: Int, x6: Int, x7: Int, x8: Int, x9: Int, x10: Int, x11: Int, x12: Int, x13: Int, x14: Int, x15: Int, x16: Int, x17: Int, x18: Int, x19: Int, x20: Int, x21: Int, x22: Int, x23: Int, x24: Int, x25: Int, x26: Int) = 42
+}
diff --git a/tests/run/structural.scala b/tests/run/structural.scala
new file mode 100644
index 000000000..0f18f4579
--- /dev/null
+++ b/tests/run/structural.scala
@@ -0,0 +1,25 @@
+case class Record(elems: (String, Any)*) extends Selectable {
+ def selectDynamic(name: String): Any = elems.find(_._1 == name).get._2
+}
+
+object Test {
+ import scala.reflect.Selectable.reflectiveSelectable
+
+ def f(closeable: { def close(): Unit }) =
+ closeable.close()
+
+ type RN = Record { val name: String; val age: Int }
+
+ def g(r: RN) = r.name
+
+ val rr: RN = Record("name" -> "Bob", "age" -> 42).asInstanceOf[RN]
+
+ def main(args: Array[String]): Unit = {
+ f(new java.io.PrintStream("foo"))
+ assert(g(rr) == "Bob")
+
+ val s: { def concat(s: String): String } = "abc"
+ assert(s.concat("def") == "abcdef")
+ }
+}
+
diff --git a/tests/run/structuralNoSuchMethod.check b/tests/run/structuralNoSuchMethod.check
new file mode 100644
index 000000000..20576fc9c
--- /dev/null
+++ b/tests/run/structuralNoSuchMethod.check
@@ -0,0 +1 @@
+no such method
diff --git a/tests/run/structuralNoSuchMethod.scala b/tests/run/structuralNoSuchMethod.scala
new file mode 100644
index 000000000..476d7ed82
--- /dev/null
+++ b/tests/run/structuralNoSuchMethod.scala
@@ -0,0 +1,23 @@
+import scala.reflect.Selectable.reflectiveSelectable
+
+/** Demonstrates limitation of structural method dispatch (in Scala 2.x and dotty).
+ * The method must be defined at exactly the argument types given in the structural type;
+ * Generic instantiation is not possible.
+ */
+object Test {
+ type T = { def f(x: String, y: String): String }
+
+ class C[X] {
+ def f(x: X, y: String): String = "f1"
+ }
+
+ val x: T = new C[String]
+
+ def main(args: Array[String]) =
+ try println(x.f("", "")) // throws NoSuchMethodException
+ catch {
+ case ex: NoSuchMethodException =>
+ println("no such method")
+ }
+
+}
diff --git a/tests/run/t10170.check b/tests/run/t10170.check
new file mode 100644
index 000000000..29d6383b5
--- /dev/null
+++ b/tests/run/t10170.check
@@ -0,0 +1 @@
+100
diff --git a/tests/run/t10170.scala b/tests/run/t10170.scala
new file mode 100644
index 000000000..683bad371
--- /dev/null
+++ b/tests/run/t10170.scala
@@ -0,0 +1,7 @@
+object Test {
+ def main(args: Array[String]) = println(f)
+
+ def f = {
+ val a = 100; ({ val a = 0; (c: Int) => c })(a)
+ }
+}
diff --git a/tests/untried/neg/valueclasses-impl-restrictions.scala b/tests/untried/neg/valueclasses-impl-restrictions.scala
deleted file mode 100644
index f0577a94a..000000000
--- a/tests/untried/neg/valueclasses-impl-restrictions.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-class M(val t: Int) extends AnyVal {
- def lazyString = {
- object X
- () => X
- }
-}
-
-class X1(val s: String) extends AnyVal {
- trait I2 {
- val q: String
- def z = s + q
- }
-
- def y(x: X1) = {
- val i2 = new I2 { val q = x.s } // allowed as of SI-7571
- i2.z
-
- { case x => x } : PartialFunction[Int, Int] // allowed
- }
-}
-
-class X2(val s: String) extends AnyVal {
- private[this] class I2(val q: String)
-
- def y(i: Int) = {
- val i2 = new I2(i.toString)
- i2.q + s
- }
-}