aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Desugar.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java4
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala19
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala3
-rw-r--r--compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala39
-rw-r--r--doc-tool/resources/_layouts/api-page.html2
-rw-r--r--doc-tool/resources/css/api-page.css5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala3
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocDriver.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala86
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala156
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/transform.scala (renamed from doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala)15
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala8
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/entities.scala3
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/traversing.scala4
-rw-r--r--project/Build.scala12
-rw-r--r--tests/run/i2020.scala8
19 files changed, 366 insertions, 20 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
index deb239143..b5be89440 100644
--- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
@@ -469,7 +469,13 @@ object desugar {
val originalVparams = constr1.vparamss.toIterator.flatten
val tparamAccessors = derivedTparams.map(_.withMods(originalTparams.next.mods))
val caseAccessor = if (isCaseClass) CaseAccessor else EmptyFlags
- val vparamAccessors = derivedVparamss.flatten.map(_.withMods(originalVparams.next.mods | caseAccessor))
+ val vparamAccessors = derivedVparamss match {
+ case first :: rest =>
+ first.map(_.withMods(originalVparams.next.mods | caseAccessor)) ++
+ rest.flatten.map(_.withMods(originalVparams.next.mods))
+ case _ =>
+ Nil
+ }
cpy.TypeDef(cdef)(
name = className,
rhs = cpy.Template(impl)(constr, parents1, self1,
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
index c74130b44..2bf15cb7c 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
@@ -49,7 +49,9 @@ public enum ErrorMessageID {
OverridesNothingButNameExistsID,
ForwardReferenceExtendsOverDefinitionID,
ExpectedTokenButFoundID,
- MixedLeftAndRightAssociativeOpsID;
+ MixedLeftAndRightAssociativeOpsID,
+ CantInstantiateAbstractClassOrTraitID,
+ ;
public int errorNumber() {
return ordinal() - 2;
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index e818e7a42..34190c114 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -1127,4 +1127,23 @@ object messages {
|""".stripMargin
}
+ case class CantInstantiateAbstractClassOrTrait(cls: Symbol, isTrait: Boolean)(implicit ctx: Context)
+ extends Message(CantInstantiateAbstractClassOrTraitID) {
+ val kind = "Usage"
+ private val traitOrAbstract = if (isTrait) hl"a trait" else hl"abstract"
+ val msg = hl"""${cls.name} is ${traitOrAbstract}; it cannot be instantiated"""
+ val explanation =
+ hl"""|Abstract classes and traits need to be extended by a concrete class or object
+ |to make their functionality accessible.
+ |
+ |You may want to create an anonymous class extending ${cls.name} with
+ | ${s"class ${cls.name} { }"}
+ |
+ |or add a companion object with
+ | ${s"object ${cls.name} extends ${cls.name}"}
+ |
+ |You need to implement any abstract members in both cases.
+ |""".stripMargin
+ }
+
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index fb0497c2b..48f9243f7 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -29,6 +29,7 @@ import ErrorReporting.{err, errorType}
import config.Printers.typr
import collection.mutable
import SymDenotations.NoCompleter
+import dotty.tools.dotc.reporting.diagnostic.messages.CantInstantiateAbstractClassOrTrait
import dotty.tools.dotc.transform.ValueClasses._
object Checking {
@@ -103,7 +104,7 @@ object Checking {
case tref: TypeRef =>
val cls = tref.symbol
if (cls.is(AbstractOrTrait))
- ctx.error(em"$cls is abstract; cannot be instantiated", pos)
+ ctx.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), pos)
if (!cls.is(Module)) {
// Create a synthetic singleton type instance, and check whether
// it conforms to the self type of the class as seen from that instance.
diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
index 37d1404bb..971a40a1b 100644
--- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
+++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
@@ -159,4 +159,43 @@ class ErrorMessagesTests extends ErrorMessagesTest {
assertEquals("+:", op2.show)
assertFalse(op2LeftAssoc)
}
+
+ @Test def cantInstantiateAbstract =
+ checkMessagesAfter("refchecks") {
+ """
+ |object Scope {
+ | abstract class Concept
+ | new Concept()
+ |}
+ """.stripMargin
+ }
+ .expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ val defn = ictx.definitions
+
+ assertMessageCount(1, messages)
+ val CantInstantiateAbstractClassOrTrait(cls, isTrait) :: Nil = messages
+ assertEquals("Concept", cls.name.show)
+ assertFalse("expected class", isTrait)
+ }
+
+ @Test def cantInstantiateTrait =
+ checkMessagesAfter("refchecks") {
+ """
+ |object Scope {
+ | trait Concept
+ | new Concept()
+ |}
+ """.stripMargin
+ }
+ .expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ val defn = ictx.definitions
+
+ assertMessageCount(1, messages)
+ val CantInstantiateAbstractClassOrTrait(cls, isTrait) :: Nil = messages
+ assertEquals("Concept", cls.name.show)
+ assertTrue("expected trait", isTrait)
+ }
+
}
diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html
index 26a4290da..878ec8d8f 100644
--- a/doc-tool/resources/_layouts/api-page.html
+++ b/doc-tool/resources/_layouts/api-page.html
@@ -95,7 +95,7 @@ extraCSS:
{% 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="expand-button {% if member.hasShortenedDocstring == false %}invisible{% endif %}" onclick="toggleMemberBody(this, '{{ member.signature }}');">[+]</span>
<span class="member-annotations">
{% for annot in member.annotations %}@{{ annot | split: '.' | last }} {% endfor %}
</span>
diff --git a/doc-tool/resources/css/api-page.css b/doc-tool/resources/css/api-page.css
index 380efb834..1dd4f559c 100644
--- a/doc-tool/resources/css/api-page.css
+++ b/doc-tool/resources/css/api-page.css
@@ -122,6 +122,11 @@ div.entity-section > div.member > div.member-title > span.expand-button:hover {
user-select: none;
}
+div.entity-section > div.member > div.member-title > span.expand-button.invisible,
+div.entity-section > div.member > div.member-title > span.expand-button.invisible:hover {
+ color: transparent;
+}
+
div.entity-section > div.member > div.member-body {
margin: 5px 0 0 39px;
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
index 708c26cc0..c5d20d30b 100644
--- a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
@@ -32,6 +32,7 @@ class DocCompiler extends Compiler {
new LinkSuperTypes,
new LinkCompanions,
new AlternateConstructors,
- new SortMembers))
+ new SortMembers)),
+ List(new StatisticsPhase)
)
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
index 515de9ae9..1434d5a49 100644
--- a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
@@ -9,6 +9,7 @@ import model.Package
import dotc.config._
import dotc.core.Comments.ContextDoc
import staticsite.Site
+import dotc.printing.Highlighting._
/** `DocDriver` implements the main entry point to the Dotty documentation
* tool. It's methods are used by the external scala and java APIs.
@@ -43,16 +44,18 @@ class DocDriver extends Driver {
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)
+ val projectName = ctx.settings.projectName.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)
+ Site(siteRoot, projectName, ctx.docbase.packages)
.generateApiDocs()
.copyStaticFiles()
.generateHtmlFiles()
.generateBlog()
+ ctx.docbase.printSummary()
System.exit(if (reporter.hasErrors) 1 else 0)
}
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
index 16f0776fa..8f463833d 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
@@ -2,9 +2,12 @@ package dotty.tools
package dottydoc
package core
-import dotc.core.Symbols.Symbol
+import dotc.core.Symbols._
+import dotc.core.Flags._
+import dotc.core.Decorators._
import dotc.core.Comments.ContextDocstrings
-import model.Package
+import model.{ Package, Entity }
+import model.comment.Comment
import dotc.core.Contexts.Context
import dotc.printing.Highlighting._
@@ -17,6 +20,12 @@ class ContextDottydoc extends ContextDocstrings {
def packages: Map[String, Package] = _packages.toMap
def packagesMutable: mutable.Map[String, Package] = _packages
+ private[this] var _statistics: Map[String, Statistics] = Map.empty
+ def registerStatistics(pkgName: String, stat: Statistics): Unit =
+ _statistics = _statistics + (pkgName -> stat)
+
+ def statistics: Map[String, Statistics] = _statistics
+
/** Should perhaps factorize this into caches that get flushed */
private var _defs: Map[Symbol, Set[Symbol]] = Map.empty
def defs(sym: Symbol): Set[Symbol] = _defs.get(sym).getOrElse(Set.empty)
@@ -49,4 +58,77 @@ class ContextDottydoc extends ContextDocstrings {
}.toString, pos)
def debug(msg: String)(implicit ctx: Context): Unit = debug(msg, NoSourcePosition)
+
+ def printSummary()(implicit ctx: Context): Unit = {
+ def colored(part: Int, total: Int) =
+ if (total == 0) "0"
+ else {
+ val percentage = (part * 100.0 / total).toInt
+ val str = s"$part/$total ($percentage%)"
+
+ if (percentage > 75) Green(str)
+ else if (percentage > 50) Yellow(str)
+ else Red(str)
+ }
+
+ val totalEntities = statistics.totalEntities
+
+ val projectName = ctx.settings.projectName.value
+ val warningsText =
+ if (ctx.reporter.hasWarnings)
+ s"total warnings with regards to compilation and documentation: ${ctx.reporter.warningCount}"
+ else ""
+
+ val api = statistics.values.iterator.map(_.api).foldLeft(Counters(0,0,0,0,0,0))(_ merge _)
+ val internalApi = statistics.values.iterator.map(_.internalApi).foldLeft(Counters(0,0,0,0,0,0))(_ merge _)
+
+ val apiSummary = (for {
+ (pkgName, stat) <- statistics.toList.sortBy(_._1)
+ } yield {
+ val pub = colored(stat.api.publicDocstrings, stat.api.publicEntities)
+ val pro = colored(stat.api.protectedDocstrings, stat.api.protectedEntities)
+ s"""|package $pkgName
+ |${Blue("-" * ctx.settings.pageWidth.value)}
+ |public: $pub \t protected: $pro
+ |""".stripMargin
+ }).mkString("\n")
+
+ val internalSummary = (for {
+ (pkgName, stat) <- statistics.toList.sortBy(_._1)
+ } yield {
+ val pub = colored(stat.internalApi.publicDocstrings, stat.internalApi.publicEntities)
+ val pro = colored(stat.internalApi.protectedDocstrings, stat.internalApi.protectedEntities)
+ val pri = colored(stat.internalApi.privateDocstrings, stat.internalApi.privateEntities)
+ s"""|package $pkgName
+ |${Blue("-" * ctx.settings.pageWidth.value)}
+ |public: $pub \t protected: $pro \t private: $pri
+ |""".stripMargin
+ }).mkString("\n")
+
+ ctx.echo {
+ s"""|${Blue("=" * ctx.settings.pageWidth.value)}
+ |Dottydoc summary report for project `$projectName`
+ |${Blue("=" * ctx.settings.pageWidth.value)}
+ |Documented members in public API:
+ |
+ |$apiSummary
+ |
+ |Summary:
+ |
+ |public members with docstrings: ${colored(api.publicDocstrings, api.publicEntities)}
+ |${hl"${"protected"}"} members with docstrings: ${colored(api.protectedDocstrings, api.protectedEntities)}
+ |${Blue("=" * ctx.settings.pageWidth.value)}
+ |
+ |Documented members in internal API:
+ |
+ |$internalSummary
+ |
+ |Summary internal API:
+ |
+ |public members with docstrings: ${colored(internalApi.publicDocstrings, internalApi.publicEntities)}
+ |${hl"${"protected"}"} members with docstrings: ${colored(internalApi.protectedDocstrings, internalApi.protectedEntities)}
+ |${hl"${"private"}"} members with docstrings: ${colored(internalApi.privateDocstrings, internalApi.privateEntities)}
+ |$warningsText""".stripMargin
+ }
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
index 460566838..7f44c5656 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
@@ -226,7 +226,7 @@ class DocASTPhase extends Phase {
override def run(implicit ctx: Context): Unit = {
currentRun += 1
- ctx.docbase.echo(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}")
+ ctx.echo(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}")
collect(ctx.compilationUnit.tpdTree) // Will put packages in `packages` var
}
@@ -237,8 +237,7 @@ class DocASTPhase extends Phase {
// (2) Set parents of entities, needed for linking
for {
- parentName <- rootPackages(packages)
- parent = packages(parentName)
+ parent <- rootPackages(packages)
child <- parent.members
} setParent(child, to = parent)
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
index 3de8f68f7..2471e9220 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
@@ -14,6 +14,7 @@ import util.syntax._
/** Phase to add docstrings to the Dottydoc AST */
class DocstringPhase extends DocMiniPhase with CommentParser with CommentCleaner {
+
private def getComment(sym: Symbol)(implicit ctx: Context): Option[CompilerComment] =
ctx.docbase.docstring(sym)
.orElse {
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
new file mode 100644
index 000000000..e7f9a9ec7
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
@@ -0,0 +1,156 @@
+package dotty.tools
+package dottydoc
+package core
+
+import dotc.core.Phases.Phase
+import dotc.core.Contexts.Context
+import dotc.core.Symbols.Symbol
+import dotc.core.Decorators._
+import dotc.core.Flags._
+import dotc.CompilationUnit
+import dottydoc.util.syntax._
+import dottydoc.util.traversing._
+
+import model._
+
+object Statistics {
+ implicit class MapTotals(val map: Map[String, Statistics]) extends AnyVal {
+ def totalEntities =
+ map.values.foldLeft(0)(_ + _.totalEntities)
+ }
+}
+
+case class Statistics(pkgName: String, api: Counters, internalApi: Counters) {
+ def totalEntities =
+ api.totalEntities + internalApi.totalEntities
+
+ def totalDocstrings =
+ api.totalDocstrings + internalApi.totalDocstrings
+}
+
+case class Counters(
+ publicEntities: Int,
+ privateEntities: Int,
+ protectedEntities: Int,
+
+ publicDocstrings: Int,
+ privateDocstrings: Int,
+ protectedDocstrings: Int
+) {
+ def totalEntities =
+ publicEntities + privateEntities + protectedEntities
+
+ def totalDocstrings =
+ publicDocstrings + privateDocstrings + protectedDocstrings
+
+ def merge(o: Counters): Counters = Counters(
+ publicEntities + o.publicEntities,
+ privateEntities + o.privateEntities,
+ protectedEntities + o.protectedEntities,
+ publicDocstrings + o.publicDocstrings,
+ privateDocstrings + o.privateDocstrings,
+ protectedDocstrings + o.protectedDocstrings
+ )
+}
+
+class StatisticsPhase extends Phase {
+
+ def phaseName = "StatisticsPhase"
+
+ override def run(implicit ctx: Context): Unit = ()
+
+ override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
+ for {
+ (pkgName, pack) <- ctx.docbase.packages
+ externalApi = collectPublicStats(pack)
+ internalApi = collectInternalStats(pack)
+ stats = Statistics(pkgName, externalApi, internalApi)
+ } ctx.docbase.registerStatistics(pkgName, stats)
+
+ units
+ }
+
+ def collectPublicStats(pack: Package)(implicit ctx: Context): Counters = {
+ var publicEntities: Int = 0
+ var protectedEntities: Int = 0
+ var publicDocstrings: Int = 0
+ var protectedDocstrings: Int = 0
+
+ if (pack.comment.isDefined) {
+ publicEntities += 1
+ publicDocstrings += 1
+ }
+
+ def doCount(sym: Symbol, comment: Int): Unit =
+ if (!sym.is(Protected)) {
+ publicEntities += 1
+ publicDocstrings += comment
+ }
+ else {
+ protectedEntities += 1
+ protectedDocstrings += comment
+ }
+
+
+ def recur(e: Entity, reachable: Boolean): Unit = {
+ val isVisible = !e.symbol.is(Private) && !e.symbol.privateWithin.exists
+ val shouldCount = isVisible && reachable
+ e match {
+ case e: Package => ()
+ case e: Entity with Members => if (shouldCount) {
+ doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ e.members.foreach { c =>
+ if (!(e.symbol.is(Final) && c.symbol.is(Protected))) recur(c, true)
+ }
+ }
+ case e =>
+ if (shouldCount) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ }
+ }
+
+ pack.members.foreach(recur(_, true))
+ Counters(publicEntities, 0, protectedEntities, publicDocstrings, 0, protectedDocstrings)
+ }
+
+ def collectInternalStats(pack: Package)(implicit ctx: Context): Counters = {
+ var publicEntities: Int = 0
+ var privateEntities: Int = 0
+ var protectedEntities: Int = 0
+ var publicDocstrings: Int = 0
+ var privateDocstrings: Int = 0
+ var protectedDocstrings: Int = 0
+
+ def doCount(sym: Symbol, comment: Int): Unit =
+ if (sym.is(Private)) {
+ privateEntities += 1
+ privateDocstrings += comment
+ }
+ else if (!sym.is(Protected)) {
+ publicEntities += 1
+ publicDocstrings += comment
+ }
+ else {
+ protectedEntities += 1
+ protectedDocstrings += comment
+ }
+
+
+ def recur(e: Entity, reachable: Boolean): Unit = {
+ val internal = !reachable || e.symbol.is(Private) || e.symbol.privateWithin.exists
+ e match {
+ case _: Package => ()
+ case e: Entity with Members =>
+ e.members.foreach { c =>
+ val childIsInternal = !internal || (e.symbol.is(Final) && c.symbol.is(Protected))
+ recur(c, childIsInternal)
+ }
+ if (internal) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ case _ =>
+ if (internal) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ }
+ }
+
+ pack.members.foreach(recur(_, true))
+ Counters(publicEntities, privateEntities, protectedEntities, publicDocstrings, privateDocstrings, protectedDocstrings)
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
index 1f30e089d..e4b9ae6b6 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
@@ -45,15 +45,15 @@ object transform {
* -------------------------
* To delete a node in the AST, simply return `NonEntity` from transforming method
*/
- abstract class DocMiniTransformations(transformations: List[DocMiniPhase]) extends Phase {
+ trait DocMiniTransformations extends Phase {
+ def transformations: List[DocMiniPhase]
override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
for {
- rootName <- rootPackages(ctx.docbase.packages)
- pack = ctx.docbase.packages(rootName)
+ pack <- rootPackages(ctx.docbase.packages)
transformed = performPackageTransform(pack)
- } yield ctx.docbase.packagesMutable(rootName) = transformed
- super.runOn(units)
+ } yield ctx.docbase.packagesMutable(pack.name) = transformed
+ units
}
private def performPackageTransform(pack: Package)(implicit ctx: Context): Package = {
@@ -197,8 +197,9 @@ object transform {
object DocMiniTransformations {
private var previousPhase = 0
- def apply(transformations: DocMiniPhase*) =
- new DocMiniTransformations(transformations.toList) {
+ def apply(miniPhases: DocMiniPhase*) =
+ new DocMiniTransformations {
+ val transformations = miniPhases.toList
val packages = Map.empty[String, Package]
def phaseName = s"MiniTransformation${ previousPhase += 1 }"
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
index e7cf54a03..239656141 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
@@ -55,6 +55,7 @@ object JavaConverters {
"comment" -> ent.comment.map(_.asJava).asJava,
"superTypes" -> ent.superTypes,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"signature" -> ent.signature
) ++ extras).asJava
}
@@ -74,6 +75,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -95,6 +97,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -115,6 +118,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -134,6 +138,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -152,6 +157,7 @@ object JavaConverters {
"paramLists" -> ent.paramLists.map(_.asJava).asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
"implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"signature" -> ent.signature
@@ -168,6 +174,7 @@ object JavaConverters {
"returnValue" -> ent.returnValue.asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
"implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"signature" -> ent.signature
@@ -183,6 +190,7 @@ object JavaConverters {
"path" -> ent.path.asJava,
"alias" -> ent.alias.map(_.asJava).asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"signature" -> ent.signature
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
index 9cbd1f6c8..d35077816 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
@@ -21,6 +21,9 @@ trait Entity { entity =>
def annotations: List[String]
+ def hasShortenedDocstring: Boolean =
+ comment.map(d => d.body.length > d.short.length).getOrElse(false)
+
def signature: String =
entity.name + (entity match {
case o: Object => "$"
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala b/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
index 9c2e3bf54..956cb9291 100644
--- a/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
@@ -24,7 +24,7 @@ object traversing {
}
- def rootPackages(pkgs: Map[String, Package]): List[String] = {
+ def rootPackages(pkgs: Map[String, Package]): List[Package] = {
var currentDepth = Int.MaxValue
var packs = List.empty[String]
@@ -38,6 +38,6 @@ object traversing {
key :: packs
} else packs
}
- packs
+ packs.map(pkgs.apply)
}
}
diff --git a/project/Build.scala b/project/Build.scala
index 1b8be35ff..376e06bb1 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -56,6 +56,9 @@ object DottyBuild extends Build {
// Compiles the documentation and static site
lazy val genDocs = inputKey[Unit]("run dottydoc to generate static documentation site")
+ // Shorthand for compiling a docs site
+ lazy val dottydoc = inputKey[Unit]("run dottydoc")
+
/** Dottydoc deps */
lazy val dottydocDeps = SettingKey[Seq[ModuleID]](
"dottydocDeps",
@@ -273,6 +276,15 @@ object DottyBuild extends Build {
)
}.evaluated,
+ dottydoc := Def.inputTaskDyn {
+ val args: Seq[String] = spaceDelimited("<arg>").parsed
+ val dottyLib = packageAll.value("dotty-library")
+ val dottyInterfaces = packageAll.value("dotty-interfaces")
+ val otherDeps = (dependencyClasspath in Compile).value.map(_.data).mkString(":")
+ val cp: Seq[String] = Seq("-classpath", s"$dottyLib:$dottyInterfaces:$otherDeps")
+ (runMain in Compile).toTask(s""" dotty.tools.dottydoc.Main ${cp.mkString(" ")} """ + args.mkString(" "))
+ }.evaluated,
+
// Override run to be able to run compiled classfiles
dotr := {
val args: Seq[String] = spaceDelimited("<arg>").parsed
diff --git a/tests/run/i2020.scala b/tests/run/i2020.scala
new file mode 100644
index 000000000..78794a590
--- /dev/null
+++ b/tests/run/i2020.scala
@@ -0,0 +1,8 @@
+object Test {
+
+ case class Foo(x: Int)(y: Int)
+
+ def main(args: Array[String]) =
+ assert(Foo(1)(1) == Foo(1)(2))
+
+}