Skip to content

Scala3doc: Add support for annotations in type parameters, add tests for external location providing, minor fixes #10833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions scala3doc-testcases/src/tests/objectSignatures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@ object Base

object A2 extends A[String] with C

object <

object >

// We are not going to add final below
// final object B
11 changes: 11 additions & 0 deletions scala3doc-testcases/src/tests/specializedSignature.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tests

package specializedSignature

import scala.{specialized}

trait AdditiveMonoid[@specialized(Int, Long, Float, Double) A]
{
def a: A
= ???
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ class ScalaExternalLocationProvider(
externalDocumentation: ExternalDocumentation,
extension: String,
kind: DocumentationKind
)(using ctx: DokkaContext) extends DefaultExternalLocationProvider(externalDocumentation, extension, ctx):
) extends ExternalLocationProvider:
def docURL = externalDocumentation.getDocumentationURL.toString.stripSuffix("/") + "/"
override def resolve(dri: DRI): String =
Option(externalDocumentation.getPackageList).map(_.getLocations.asScala.toMap).flatMap(_.get(dri.toString))
.fold(constructPath(dri))( l => {
this.getDocURL + l
this.docURL + l
}
)

private val originRegex = raw"\[origin:(.*)\]".r

override def constructPath(dri: DRI): String = kind match {
def constructPath(dri: DRI): String = kind match {
case DocumentationKind.Javadoc => constructPathForJavadoc(dri)
case DocumentationKind.Scaladoc => constructPathForScaladoc(dri)
case DocumentationKind.Scala3doc => constructPathForScala3doc(dri)
Expand All @@ -38,17 +39,17 @@ class ScalaExternalLocationProvider(
val location = "\\$+".r.replaceAllIn(dri.location.replace(".","/"), _ => ".")
val origin = originRegex.findFirstIn(dri.extra)
val anchor = dri.anchor
getDocURL + location + extension + anchor.fold("")(a => s"#$a")
docURL + location + extension + anchor.fold("")(a => s"#$a")
}

private def constructPathForScaladoc(dri: DRI): String = {
val location = dri.location.replace(".","/")
val anchor = dri.anchor
getDocURL + location + extension + anchor.fold("")(a => s"#$a")
docURL + location + extension + anchor.fold("")(a => s"#$a")
}

private def constructPathForScala3doc(dri: DRI): String = {
val location = dri.location.replace(".","/")
val anchor = dri.anchor
getDocURL + location + anchor.fold(extension)(a => s"/$a$extension")
docURL + location + anchor.fold(extension)(a => s"/$a$extension")
}
1 change: 1 addition & 0 deletions scala3doc/src/dotty/dokka/model/api/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ case class Parameter(
)

case class TypeParameter(
annotations: Seq[Annotation],
variance: "" | "+" | "-",
name: String,
dri: DRI,
Expand Down
19 changes: 13 additions & 6 deletions scala3doc/src/dotty/dokka/tasty/BasicSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@ trait BasicSupport:
export SymOps._

def parseAnnotation(annotTerm: Term): Annotation =
import dotty.tools.dotc.ast.Trees.{SeqLiteral}
val dri = annotTerm.tpe.typeSymbol.dri
def inner(t: Term): List[Annotation.AnnotationParameter] = t match {
case i: Ident => List(Annotation.LinkParameter(None, i.tpe.typeSymbol.dri, i.name))
case Typed(term, tpeTree) => inner(term)
case SeqLiteral(args, tpeTree) => args.map(_.asInstanceOf[Term]).flatMap(inner)
case Literal(constant) => List(Annotation.PrimitiveParameter(None, constant.show))
case NamedArg(name, Literal(constant)) => List(Annotation.PrimitiveParameter(Some(name), constant.show))
case x @ Select(qual, name) => List.empty
case other => List(Annotation.UnresolvedParameter(None, other.show))
}


val params = annotTerm match
case Apply(target, appliedWith) => {
appliedWith.flatMap {
case Literal(constant) => Some(Annotation.PrimitiveParameter(None, constant.show))
case NamedArg(name, Literal(constant)) => Some(Annotation.PrimitiveParameter(Some(name), constant.show))
case x @ Select(qual, name) => None
case other => Some(Annotation.UnresolvedParameter(None, other.show))
}
appliedWith.flatMap(inner)
}

Annotation(dri, params)
Expand Down
1 change: 1 addition & 0 deletions scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ trait ClassLikeSupport:
else ""

TypeParameter(
argument.symbol.getAnnotations(),
variancePrefix,
argument.symbol.normalizedName,
argument.symbol.dri,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ trait SignatureBuilder extends ScalaSignatureUtils {
def annotationsInline(d: Parameter): SignatureBuilder =
d.annotations.foldLeft(this){ (bdr, annotation) => bdr.buildAnnotation(annotation) }

def annotationsInline(t: TypeParameter): SignatureBuilder =
t.annotations.foldLeft(this){ (bdr, annotation) => bdr.buildAnnotation(annotation) }

private def buildAnnotation(a: Annotation): SignatureBuilder =
text("@").driLink(a.dri.location.split('.').last, a.dri).buildAnnotationParams(a).text(" ")

Expand Down Expand Up @@ -77,7 +80,7 @@ trait SignatureBuilder extends ScalaSignatureUtils {
text(all.toSignatureString()).text(kind + " ")

def generics(on: Seq[TypeParameter]) = list(on.toList, "[", "]"){ (bdr, e) =>
bdr.text(e.variance).memberName(e.name, e.dri).signature(e.signature)
bdr.annotationsInline(e).text(e.variance).memberName(e.name, e.dri).signature(e.signature)
}

def functionParameters(params: Seq[ParametersList]) =
Expand Down
76 changes: 76 additions & 0 deletions scala3doc/test/dotty/dokka/ExternalLocationProviderTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package dotty.dokka

import org.jetbrains.dokka.pages.ContentPage
import org.jetbrains.dokka.pages.PageNode
import org.jetbrains.dokka.pages.RootPageNode
import org.jetbrains.dokka.pages.ModulePage
import org.jetbrains.dokka.pages.ClasslikePageNode
import org.jetbrains.dokka.model.DPackage
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.base.resolvers.external._
import org.jetbrains.dokka.base.resolvers.shared.{ExternalDocumentation => ED, _}
import org.jetbrains.dokka.base.resolvers.local._
import org.jetbrains.dokka.model.DisplaySourceSet
import dotty.dokka.withNoOrigin
import dotty.dokka.tasty._

import scala.collection.JavaConverters._
import java.nio.file.Paths
import java.nio.file.Path
import scala.util.matching._
import dotty.dokka.model.api._
import java.net.URL
import org.junit.{Test}
import org.junit.Assert._

import scala.quoted._

class ExternalLocationProviderTest:
def createExternalLocationProvider(docURL: String, ext: String, kind: DocumentationKind) = {
val emptyExtDoc = ED(
URL(docURL),
PackageList(
RecognizedLinkFormat.Javadoc1, JSet(), JMap(), URL(docURL)
)
)
ScalaExternalLocationProvider(emptyExtDoc, ext, kind)
}

def testResolvedLinks(provider: ScalaExternalLocationProvider, testcases: List[(DRI, String)]) = testcases.foreach {
case (dri, expect) => assertEquals(provider.resolve(dri), expect)
}

@Test
def javadocExternalLocationProviderTest(): Unit = {
val provider = createExternalLocationProvider("https://docs.oracle.com/javase/8/docs/api/", ".html", DocumentationKind.Javadoc)
val testcases = List(
(DRI("java.util.Map$$Entry"), "https://docs.oracle.com/javase/8/docs/api/java/util/Map.Entry.html"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we add a tests for method base DRI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna make task for that because linking to methods (anchors) are still TODO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(DRI("javax.swing.plaf.nimbus.AbstractRegionPainter$$PaintContext$$CacheMode"), "https://docs.oracle.com/javase/8/docs/api/javax/swing/plaf/nimbus/AbstractRegionPainter.PaintContext.CacheMode.html"),
(DRI("java.lang.CharSequence"), "https://docs.oracle.com/javase/8/docs/api/java/lang/CharSequence.html")
)
testResolvedLinks(provider, testcases)
}

@Test
def scaladocExternalLocationProviderTest(): Unit = {
val provider = createExternalLocationProvider("https://www.scala-lang.org/api/current/", ".html", DocumentationKind.Scaladoc)
val testcases = List(
(DRI("scala.Predef$"),"https://www.scala-lang.org/api/current/scala/Predef$.html"),
(DRI("scala.util.package$$chaining$"), "https://www.scala-lang.org/api/current/scala/util/package$$chaining$.html"),
(DRI("scala.util.Using$"), "https://www.scala-lang.org/api/current/scala/util/Using$.html"),
(DRI("scala.util.matching.Regex$$Match"), "https://www.scala-lang.org/api/current/scala/util/matching/Regex$$Match.html")
)
testResolvedLinks(provider, testcases)
}

@Test
def scala3docExternalLocationProviderTest(): Unit = {
val provider = createExternalLocationProvider("https://dotty.epfl.ch/api/", ".html", DocumentationKind.Scala3doc)
val testcases = List(
(DRI("scala.Predef$"),"https://dotty.epfl.ch/api/scala/Predef$.html"),
(DRI("scala.util.package$$chaining$"), "https://dotty.epfl.ch/api/scala/util/package$$chaining$.html"),
(DRI("scala.util.Using$"), "https://dotty.epfl.ch/api/scala/util/Using$.html"),
(DRI("scala.util.matching.Regex$$Match"), "https://dotty.epfl.ch/api/scala/util/matching/Regex$$Match.html")
)
testResolvedLinks(provider, testcases)
}
4 changes: 3 additions & 1 deletion scala3doc/test/dotty/dokka/SignatureTestCases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,6 @@ class ImplicitConversionsTest3 extends SignatureTest(
SignatureTest.all,
sourceFiles = List("implicitConversions2"),
filterFunc = _.toString.endsWith("ClassWithConversionWithProperType.html")
)
)

class SpecializedSignature extends SignatureTest("specializedSignature", SignatureTest.all)