diff options
13 files changed, 98 insertions, 35 deletions
diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 86f34e64d..e20f846ac 100644 --- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -6,6 +6,7 @@ import parsing.Tokens._ import scala.annotation.switch import scala.collection.mutable.StringBuilder import core.Contexts.Context +import util.Chars.{ LF, FF, CR, SU } import Highlighting.{Highlight, HighlightBuffer} /** This object provides functions for syntax highlighting in the REPL */ @@ -26,7 +27,7 @@ object SyntaxHighlighting { private def valDef(str: String) = ValDefColor + str + NoColor private def operator(str: String) = TypeColor + str + NoColor private def annotation(str: String) = - if (str.trim == "@") str else AnnotationColor + str + NoColor + if (str.trim == "@") str else { AnnotationColor + str + NoColor } private val tripleQs = Console.RED_B + "???" + NoColor private val keywords: Seq[String] = for { @@ -152,7 +153,11 @@ object SyntaxHighlighting { var open = 1 while (open > 0 && remaining.nonEmpty) { curr = takeChar() - newBuf += curr + if (curr == '@') { + appendWhile('@', !typeEnders.contains(_), annotation) + newBuf append CommentColor + } + else newBuf += curr if (curr == '*' && remaining.nonEmpty) { curr = takeChar() @@ -163,6 +168,11 @@ object SyntaxHighlighting { newBuf += curr if (curr == '*') open += 1 } + + (curr: @switch) match { + case LF | FF | CR | SU => newBuf append CommentColor + case _ => () + } } prev = curr newBuf append NoColor @@ -236,6 +246,11 @@ object SyntaxHighlighting { newBuf += curr closing = 0 } + + (curr: @switch) match { + case LF | FF | CR | SU => newBuf append LiteralColor + case _ => () + } } newBuf append NoColor prev = curr diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index 190445d60..17eb8d39b 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -5,9 +5,12 @@ package reporting import core.Contexts.Context import core.Decorators._ import printing.Highlighting.{Blue, Red} +import printing.SyntaxHighlighting import diagnostic.{ErrorMessageID, Message, MessageContainer, NoExplanation} import diagnostic.messages._ import util.SourcePosition +import util.Chars.{ LF, CR, FF, SU } +import scala.annotation.switch import scala.collection.mutable @@ -38,20 +41,37 @@ trait MessageRendering { */ def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = { var maxLen = Int.MinValue - def render(xs: List[Int]) = - xs.map(pos.source.offsetToLine(_)) - .map { lineNbr => - val prefix = s"${lineNbr + 1} |" - maxLen = math.max(maxLen, prefix.length) - (prefix, pos.lineContent(lineNbr).stripLineEnd) - } - .map { case (prefix, line) => - val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix) - hl"$lnum$line" - } + def render(offsetAndLine: (Int, String)): String = { + val (offset, line) = offsetAndLine + val lineNbr = pos.source.offsetToLine(offset) + val prefix = s"${lineNbr + 1} |" + maxLen = math.max(maxLen, prefix.length) + val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix).show + lnum + line.stripLineEnd + } + + def linesFrom(arr: Array[Char]): List[String] = { + def pred(c: Char) = (c: @switch) match { + case LF | CR | FF | SU => true + case _ => false + } + val (line, rest0) = arr.span(!pred(_)) + val (_, rest) = rest0.span(pred) + new String(line) :: { if (rest.isEmpty) Nil else linesFrom(rest) } + } + val syntax = + if (ctx.settings.color.value != "never") + SyntaxHighlighting(pos.linesSlice).toArray + else pos.linesSlice + val lines = linesFrom(syntax) val (before, after) = pos.beforeAndAfterPoint - (render(before), render(after), maxLen) + + ( + before.zip(lines).map(render), + after.zip(lines.drop(before.length)).map(render), + maxLen + ) } /** The column markers aligned under the error */ diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala index aad4995d8..be5c46995 100644 --- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala +++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala @@ -12,9 +12,14 @@ extends interfaces.SourcePosition { def lineContent: String = source.lineContent(point) def point: Int = pos.point + /** The line of the position, starting at 0 */ def line: Int = source.offsetToLine(point) + /** Extracts the lines from the underlying source file as `Array[Char]`*/ + def linesSlice: Array[Char] = + source.content.slice(source.startOfLine(start), source.nextLine(end)) + /** The lines of the position */ def lines: List[Int] = List.range(source.offsetToLine(start), source.offsetToLine(end + 1)) match { @@ -25,9 +30,6 @@ extends interfaces.SourcePosition { def lineOffsets: List[Int] = lines.map(source.lineToOffset(_)) - def lineContent(lineNumber: Int): String = - source.lineContent(source.lineToOffset(lineNumber)) - def beforeAndAfterPoint: (List[Int], List[Int]) = lineOffsets.partition(_ <= point) diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html index 878ec8d8f..2d2f0265a 100644 --- a/doc-tool/resources/_layouts/api-page.html +++ b/doc-tool/resources/_layouts/api-page.html @@ -134,12 +134,25 @@ extraCSS: {% endfor %} {% endif %} - {% if member.kind == "type" and member.alias != null %} + {% if member.kind == "type" %} + {% for tparam in member.typeParams %} + {% if forloop.first %} + <span class="no-left">[</span> + {% endif %} + {% if forloop.last %} + <span class="no-left">{{ tparam }}</span> + <span class="no-left">]</span> + {% else %} + <span class="no-left">{{ tparam }}, </span> + {% endif %} + {% endfor %} + {% if member.alias != null %} <span class="type-alias"> <span class="equals"> = </span> {% renderRef member.alias %} </span> {% endif %} + {% endif %} {% if member.returnValue %} <span class="no-left">: {% renderRef member.returnValue %}</span> diff --git a/doc-tool/resources/css/dottydoc.css b/doc-tool/resources/css/dottydoc.css index 7e7c501bf..0b833830c 100644 --- a/doc-tool/resources/css/dottydoc.css +++ b/doc-tool/resources/css/dottydoc.css @@ -328,3 +328,9 @@ pre > code.hljs { padding: 10px; background: transparent; } + +blockquote { + padding: 0 1em; + color: #777; + border-left: 0.25em solid #ddd; +} diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala index 7f44c5656..cfb66fa56 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -8,7 +8,7 @@ import dotc.CompilationUnit import dotc.config.Printers.dottydoc import dotc.core.Contexts.Context import dotc.core.Comments.ContextDocstrings -import dotc.core.Types.NoType +import dotc.core.Types.{PolyType, NoType} import dotc.core.Phases.Phase import dotc.core.Symbols.{ Symbol, NoSymbol } @@ -92,8 +92,16 @@ class DocASTPhase extends Phase { 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)) + else { + val tparams = t.rhs.tpe match { + case tp: PolyType => tp.paramRefs.zip(tp.variances).map { case (tp, variance) => + val varianceSym = if (variance == 1) "+" else if (variance == -1) "-" else "" + varianceSym + tp.paramName.show + } + case _ => Nil + } + TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams) + } /** trait */ case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) => diff --git a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala index e4b9ae6b6..5174c0922 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala @@ -92,6 +92,7 @@ object transform { t.name, t.path, t.alias, + t.typeParams, t.comment, t.parent ) diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala index 239656141..4a9bfce0c 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala @@ -189,6 +189,7 @@ object JavaConverters { "name" -> ent.name, "path" -> ent.path.asJava, "alias" -> ent.alias.map(_.asJava).asJava, + "typeParams" -> ent.typeParams.asJava, "comment" -> ent.comment.map(_.asJava).asJava, "hasShortenedDocstring" -> ent.hasShortenedDocstring, "isPrivate" -> ent.isPrivate, 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 b7a33a7ef..5ff28f914 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala @@ -6,6 +6,7 @@ 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 dotty.tools.dotc.core.Decorators._ import scala.collection.mutable import dotty.tools.dotc.config.Printers.dottydoc import scala.util.matching.Regex @@ -196,7 +197,7 @@ trait CommentParser extends util.MemberLookup { ) for ((key, _) <- bodyTags) ctx.docbase.warn( - s"Tag '@${key.name}' is not recognised", + hl"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 diff --git a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala index d35077816..d0f1a82c7 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala @@ -108,7 +108,7 @@ trait Package extends Entity with Members with SuperTypes { val kind = "package" } -trait TypeAlias extends Entity with Modifiers { +trait TypeAlias extends Entity with Modifiers with TypeParams { val kind = "type" def alias: Option[Reference] def isAbstract: Boolean = !alias.isDefined diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala index 568b532b7..3e766a990 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala @@ -4,7 +4,8 @@ package model import comment._ import references._ import dotty.tools.dotc -import dotc.core.Types._ +import dotc.core.Types +import Types._ import dotc.core.TypeApplications._ import dotc.core.Contexts.Context import dotc.core.Symbols.{ Symbol, ClassSymbol } @@ -105,17 +106,8 @@ object factories { 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)") - } + case tl: PolyType => + expandTpe(tl.resType) case OrType(left, right) => OrTypeReference(expandTpe(left), expandTpe(right)) @@ -148,6 +140,8 @@ object factories { prefix + tp.name.show.split("\\$").last } .toList + case tp: Types.TypeAlias => + typeParams(tp.alias.typeSymbol) case _ => Nil } diff --git a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala index bf50c0232..b50c93ee5 100644 --- a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala +++ b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala @@ -31,6 +31,7 @@ object internal { name: String, path: List[String], alias: Option[Reference], + typeParams: List[String] = Nil, var comment: Option[Comment] = None, var parent: Entity = NonEntity ) extends TypeAlias diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala index cd2ea587d..bc4a74c4f 100644 --- a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala +++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala @@ -180,6 +180,7 @@ object tags { 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 (t: Title, _) => renderTitle(t, "./") // file is in top dir case _ => null } } |