Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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: 3 additions & 1 deletion library/src/scala/annotation/constructorOnly.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ import scala.annotation.meta.*
* class fields. But it is checked that the field is eliminated before code
* is generated.
*/
@param @field class constructorOnly extends scala.annotation.StaticAnnotation
@param @field
@documented
class constructorOnly extends scala.annotation.StaticAnnotation
10 changes: 10 additions & 0 deletions library/src/scala/annotation/documented.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package scala.annotation

// TODO: Write the actual scaladoc of this annotation

// The annotation from Java is a simple hack as both have the same semantic
// meaning, only this one should be used by Scala code and the second
// annotation by Java Code
// @documented (TODO: can we make it work without breaking the cycle detection algorithm?)
@java.lang.annotation.Documented
final class documented extends StaticAnnotation
1 change: 1 addition & 0 deletions library/src/scala/annotation/experimental.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ import language.experimental.captureChecking
* @see [[https://dotty.epfl.ch/docs/reference/other-new-features/experimental-defs]]
* @syntax markdown
*/
@documented
final class experimental(message: String) extends StaticAnnotation:
def this() = this("")
1 change: 1 addition & 0 deletions library/src/scala/annotation/static.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ import scala.annotation.meta.*
@beanSetter
@param
@setter
@documented
final class static extends StaticAnnotation
1 change: 1 addition & 0 deletions library/src/scala/annotation/targetName.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ import language.experimental.captureChecking
* definition, its implementation will use the name `extname` instead of
* the regular name.
*/
@documented
final class targetName(name: String) extends StaticAnnotation
1 change: 1 addition & 0 deletions library/src/scala/annotation/threadUnsafe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import language.experimental.captureChecking
* When this annotation is used, the initialization of the lazy val will use a
* faster mechanism which is not thread-safe.
*/
@documented
final class threadUnsafe extends StaticAnnotation
1 change: 1 addition & 0 deletions library/src/scala/annotation/varargs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ import scala.language.`2.13`
* Java varargs-style forwarder method for interop. This annotation can
* only be applied to methods with repeated parameters.
*/
@documented
final class varargs extends scala.annotation.StaticAnnotation
6 changes: 3 additions & 3 deletions library/src/scala/caps/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package caps

import language.experimental.captureChecking

import annotation.{experimental, compileTimeOnly, retainsCap}
import annotation.{experimental, documented, compileTimeOnly, retainsCap}

/**
* Base trait for classes that represent capabilities in the
Expand Down Expand Up @@ -119,10 +119,10 @@ final class reserve extends annotation.StaticAnnotation
/** Allowed only for source versions up to 3.7:
* An annotation on parameters `x` stating that the method's body makes
* use of the reach capability `x*`. Consequently, when calling the method
* we need to charge the deep capture set of the actual argiment to the
* we need to charge the deep capture set of the actual argument to the
* environment.
*/
@experimental
@experimental @documented
Copy link
Member Author

Choose a reason for hiding this comment

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

One change compared to the previous behavior, this means all the @use annotations of CC will be in the doc even when we suppress cc in scaladoc.

final class use extends annotation.StaticAnnotation

/** A trait that used to allow expressing existential types. Replaced by
Expand Down
3 changes: 3 additions & 0 deletions library/src/scala/specialized.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ package scala

import scala.language.`2.13`

import scala.annotation.documented

import Specializable._

/** Annotate type parameters on which code should be automatically
Expand All @@ -30,6 +32,7 @@ import Specializable._
*/
// class tspecialized[T](group: Group[T]) extends scala.annotation.StaticAnnotation {

@documented
final class specialized(group: SpecializedGroup) extends scala.annotation.StaticAnnotation {
def this(types: Specializable*) = this(new Group(types.toList))
def this() = this(Primitives)
Expand Down
3 changes: 3 additions & 0 deletions library/src/scala/throws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ package scala

import scala.language.`2.13`

import scala.annotation.documented

/**
* Annotation for specifying the exceptions thrown by a method.
* For example:
Expand All @@ -25,6 +27,7 @@ import scala.language.`2.13`
* }
* }}}
*/
@documented
final class throws[T <: Throwable](cause: String = "") extends scala.annotation.StaticAnnotation {
def this(clazz: Class[T]) = this("")
}
4 changes: 3 additions & 1 deletion library/src/scala/transient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
package scala

import scala.language.`2.13`

import scala.annotation.documented
import scala.annotation.meta._

@field
@field @documented
final class transient extends scala.annotation.StaticAnnotation
4 changes: 3 additions & 1 deletion library/src/scala/volatile.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
package scala

import scala.language.`2.13`

import scala.annotation.documented
import scala.annotation.meta._

@field
@field @documented
final class volatile extends scala.annotation.StaticAnnotation
2 changes: 2 additions & 0 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,7 @@ object Build {
file(s"${baseDirectory.value}/src/scala/annotation/retainsByName.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/threadUnsafe.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/constructorOnly.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/documented.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/experimental.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/MacroAnnotation.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/alpha.scala"),
Expand Down Expand Up @@ -1276,6 +1277,7 @@ object Build {
file(s"${baseDirectory.value}/src/scala/annotation/retainsByName.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/threadUnsafe.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/constructorOnly.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/documented.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/experimental.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/MacroAnnotation.scala"),
file(s"${baseDirectory.value}/src/scala/annotation/alpha.scala"),
Expand Down
1 change: 0 additions & 1 deletion scaladoc-testcases/src/tests/namedTuples.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package tests.namedTuples

import language.experimental.namedTuples
import NamedTuple.*

type Person = (name: String, age: Int)
Expand Down
14 changes: 7 additions & 7 deletions scaladoc-testcases/src/tests/refinedFunctionTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ package refinedFunctionTypes
import annotation.experimental

@experimental
infix type $throws[R, +E <: Exception] = CanThrow[E] ?=> R
infix type $throws[R, +E <: Exception] = CanThrow[E] ?=> R //expected: @experimental infix type $throws[R, +E <: Exception] = CanThrow[E] ?=> R

@experimental
infix type $throws2[+E <: Exception] = (c: CanThrow[E]) ?=> c.type
infix type $throws2[+E <: Exception] = (c: CanThrow[E]) ?=> c.type //expected: @experimental infix type $throws2[+E <: Exception] = (c: CanThrow[E]) ?=> c.type

@experimental
infix type $throws3[+E <: Exception] = [T] => (c: CanThrow[E]) ?=> c.type
infix type $throws3[+E <: Exception] = [T] => (c: CanThrow[E]) ?=> c.type //expected: @experimental infix type $throws3[+E <: Exception] = [T] => (c: CanThrow[E]) ?=> c.type

@experimental
infix type $throws4[+E <: Exception] = [T] => (c: CanThrow[E]) ?=> T //expected: infix type $throws4[+E <: Exception] = [T] => CanThrow[E] ?=> T
infix type $throws4[+E <: Exception] = [T] => (c: CanThrow[E]) ?=> T //expected: @experimental infix type $throws4[+E <: Exception] = [T] => CanThrow[E] ?=> T

type TA1 = (a: Int, b: (Boolean, String)) => List[(a.type, b.type)]

type TA2 = (a: Int, b: (Boolean, String)) ?=> List[Boolean]

@experimental
type TB0 = [R, E <: Exception] =>> PolyFunction { def apply[T](c: CanThrow[E]): R; } //expected: type TB0[R, E <: Exception] = [T] => CanThrow[E] => R
type TB0 = [R, E <: Exception] =>> PolyFunction { def apply[T](c: CanThrow[E]): R; } //expected: @experimental type TB0[R, E <: Exception] = [T] => CanThrow[E] => R

@experimental
type TB1 = [R, E <: Exception] =>> PolyFunction { def apply[T](c: CanThrow[E], y: c.type): R; } //expected: type TB1[R, E <: Exception] = [T] => (c: CanThrow[E], y: c.type) => R
type TB1 = [R, E <: Exception] =>> PolyFunction { def apply[T](c: CanThrow[E], y: c.type): R; } //expected: @experimental type TB1[R, E <: Exception] = [T] => (c: CanThrow[E], y: c.type) => R

@experimental
type TB2 = [R, E <: Exception] =>> PolyFunction { def apply[T](using c: CanThrow[E]): c.type; } //expected: type TB2[R, E <: Exception] = [T] => (c: CanThrow[E]) ?=> c.type
type TB2 = [R, E <: Exception] =>> PolyFunction { def apply[T](using c: CanThrow[E]): c.type; } //expected: @experimental type TB2[R, E <: Exception] = [T] => (c: CanThrow[E]) ?=> c.type

type TC1 = [T] => (a: T) => T //expected: type TC1 = [T] => T => T

Expand Down
32 changes: 9 additions & 23 deletions scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,15 @@ trait BasicSupport:
def documentation = parseComment(sym.docstring.getOrElse(""), sym.tree)

def getAnnotations(): List[Annotation] =
// Custom annotations should be documented only if annotated by @java.lang.annotation.Documented
// We allow also some special cases
val fqNameAllowlist0 = Set(
"scala.specialized",
"scala.throws",
"scala.transient",
"scala.volatile",
"scala.annotation.experimental",
"scala.annotation.constructorOnly",
"scala.annotation.static",
"scala.annotation.targetName",
"scala.annotation.threadUnsafe",
"scala.annotation.varargs",
Comment on lines -47 to -56
Copy link
Member Author

Choose a reason for hiding this comment

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

This list was useless as all the symbols in the annotations are symbols to the constructors.
As an example, we should have had scala.annotation.experimental.<init> instead of scala.annotation.experimental.
Since the intention is to have these annotations as documented, I will update the tests that failed to include them.

)
val fqNameAllowlist =
if ccEnabled then
fqNameAllowlist0 + CaptureDefs.useAnnotFullName
else fqNameAllowlist0
val documentedSymbol = summon[Quotes].reflect.Symbol.requiredClass("java.lang.annotation.Documented")
val annotations = sym.annotations.filter { a =>
a.tpe.typeSymbol.hasAnnotation(documentedSymbol) || fqNameAllowlist.contains(a.symbol.fullName)
}
annotations.map(parseAnnotation).reverse
sym.annotations
.filter(a => a.tpe.typeSymbol.isDocumented)
.map(parseAnnotation)
.reverse

def isDocumented: Boolean =
val javaDocumentedSymbol = reflect.Symbol.requiredClass("java.lang.annotation.Documented")
val scalaDocumentedSymbol = reflect.Symbol.requiredClass("scala.annotation.documented")
sym.hasAnnotation(scalaDocumentedSymbol) || sym.hasAnnotation(javaDocumentedSymbol)

def isDeprecated(): Option[Annotation] =
sym.annotations.find { a =>
Expand Down
Loading