Skip to content

Commit 7af9a40

Browse files
committed
fix uncompiling snippets and incorrect indentation for reflection snippet docs
1 parent e835668 commit 7af9a40

File tree

10 files changed

+105
-96
lines changed

10 files changed

+105
-96
lines changed

library/src/scala/Tuple.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,11 @@ object Tuple {
156156
/** Filters out those members of the tuple for which the predicate `P` returns `false`.
157157
* A predicate `P[X]` is a type that can be either `true` or `false`. For example:
158158
* ```scala
159-
* type IsString[x] = x match {
159+
* type IsString[x] <: Boolean = x match {
160160
* case String => true
161161
* case _ => false
162162
* }
163-
* Filter[(1, "foo", 2, "bar"), IsString] =:= ("foo", "bar")
163+
* summon[Tuple.Filter[(1, "foo", 2, "bar"), IsString] =:= ("foo", "bar")]
164164
* ```
165165
* @syntax markdown
166166
*/

library/src/scala/quoted/Exprs.scala

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ object Exprs:
55
/** Matches literal sequence of literal constant value expressions and return a sequence of values.
66
*
77
* Usage:
8-
* ```scala sc:nocompile
8+
* ```scala sc:macrocompile
99
* inline def sum(args: Int*): Int = ${ sumExpr('args) }
1010
* def sumExpr(argsExpr: Expr[Seq[Int]])(using Quotes): Expr[Int] = argsExpr match
11-
* case Varargs(Exprs(args)) =>
12-
* case Varargs(Exprs(args)) =>
11+
* case Varargs(Exprs(args)) => ???
1312
* // args: Seq[Int]
14-
* ...
15-
* }
1613
* ```
1714
* To directly get the value of all expressions in a sequence `exprs: Seq[Expr[T]]` consider using `exprs.map(_.value)`/`exprs.map(_.valueOrError)` instead.
1815
*/

library/src/scala/quoted/Quotes.scala

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import scala.reflect.TypeTest
66
/** Current Quotes in scope
77
*
88
* Usage:
9-
* ```scala sc:nocompile
9+
* ```scala
10+
* import scala.quoted._
1011
* def myExpr[T](using Quotes): Expr[T] = {
1112
* import quotes.reflect._
12-
* ...
13+
* ???
1314
* }
1415
* ```
1516
*/
@@ -2532,17 +2533,11 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
25322533
/** Convert this `TypeRepr` to an `Type[?]`
25332534
*
25342535
* Usage:
2535-
* ```scala
2536-
* //{
2537-
* def f(using Quotes) = {
2536+
* ```scala sc:usingquotes
25382537
* val typeRepr: TypeRepr = ???
2539-
* //}
25402538
* typeRepr.asType match
25412539
* case '[t] =>
25422540
* '{ val x: t = ??? }
2543-
* //{
2544-
* }
2545-
* //}
25462541
* ```
25472542
*/
25482543
def asType: Type[?]

library/src/scala/quoted/Type.scala

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,13 @@ object Type:
2626
* Returns None if the type is not a singleton constant type.
2727
*
2828
* Example usage:
29-
* ```scala
30-
* //{
29+
* ```scala sc:usingquotes
3130
* import scala.deriving.*
32-
* def f(using Quotes) = {
3331
* import quotes.reflect.*
3432
* val expr: Expr[Any] = ???
35-
* //}
36-
* expr match {
33+
* expr match
3734
* case '{ $mirrorExpr : Mirror.Sum { type MirroredLabel = label } } =>
3835
* Type.valueOfConstant[label] // Option[String]
39-
* }
40-
* //{
41-
* }
42-
* //}
4336
* ```
4437
*/
4538
def valueOfConstant[T](using Type[T])(using Quotes): Option[T] =
@@ -50,20 +43,14 @@ object Type:
5043
* Returns None if the type is not a tuple singleton constant types.
5144
*
5245
* Example usage:
53-
* ```scala
46+
* ```scala sc:usingquotes
5447
* //{
5548
* import scala.deriving.*
56-
* def f(using Quotes) = {
5749
* import quotes.reflect.*
5850
* val expr: Expr[Any] = ???
59-
* //}
60-
* expr match {
51+
* expr match
6152
* case '{ type label <: Tuple; $mirrorExpr : Mirror.Sum { type MirroredElemLabels = `label` } } =>
6253
* Type.valueOfTuple[label] // Option[Tuple]
63-
* }
64-
* //{
65-
* }
66-
* //}
6754
* ```
6855
*/
6956
@since("3.1")

library/src/scala/quoted/Varargs.scala

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,9 @@ object Varargs {
1616
* `'{ Seq($e1, $e2, ...) }` typed as an `Expr[Seq[T]]`
1717
*
1818
* Usage:
19-
* ```scala
20-
* //{
21-
* def f(using Quotes) = {
19+
* ```scala sc:usingquotes
2220
* import quotes.reflect.*
23-
* //}
2421
* '{ List(${Varargs(List('{1}, '{2}, '{3}))}: _*) } // equivalent to '{ List(1, 2, 3) }
25-
* //{
26-
* }
27-
* //}
2822
* ```
2923
*/
3024
def apply[T](xs: Seq[Expr[T]])(using Type[T])(using Quotes): Expr[Seq[T]] = {
@@ -35,19 +29,12 @@ object Varargs {
3529
/** Matches a literal sequence of expressions and return a sequence of expressions.
3630
*
3731
* Usage:
38-
* ```scala sc:nocompile
39-
* //{
40-
* object O {
41-
* //}
32+
* ```scala sc:macrocompile
4233
* inline def sum(args: Int*): Int = ${ sumExpr('args) }
4334
* def sumExpr(argsExpr: Expr[Seq[Int]])(using Quotes): Expr[Int] = argsExpr match
44-
* case Varargs(argVarargs) =>
35+
* case Varargs(argVarargs) => ???
4536
* // argVarargs: Seq[Expr[Int]]
46-
* ???
47-
* //{
48-
* }
49-
* //}
50-
* ```
37+
*
5138
*/
5239
def unapply[T](expr: Expr[Seq[T]])(using Quotes): Option[Seq[Expr[T]]] = {
5340
import quotes.reflect._

project/Build.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,8 +1845,7 @@ object ScaladocConfigs {
18451845
.add(VersionsDictionaryUrl("https://scala-lang.org/api/versions.json"))
18461846
.add(DocumentSyntheticTypes(true))
18471847
.add(SnippetCompiler(List(
1848-
s"${dottyLibRoot}/scala/quoted=compile",
1849-
s"${dottyLibRoot}/scala/compiletime=compile"
1848+
s"${dottyLibRoot}/scala=compile",
18501849
)))
18511850
.add(SiteRoot("docs"))
18521851
.add(ApiSubdirectory(true))

scaladoc-testcases/src/tests/snippetCompilerTests.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,24 @@ class A {
5454
*/
5555
class B { }
5656

57+
/**
58+
* ```scala sc:macrocompile
59+
* inline def sum(args: Int*): Int = ${ sumExpr('args) }
60+
* def sumExpr(argsExpr: Expr[Seq[Int]])(using Quotes): Expr[Int] = argsExpr match
61+
* case Varargs(Exprs(args)) => ???
62+
* // args: Seq[Int]
63+
* ```
64+
*/
65+
class C { }
66+
67+
/**
68+
* ```scala sc:usingquotes
69+
* import quotes.reflect.*
70+
* '{ List(${Varargs(List('{1}, '{2}, '{3}))}: _*) } // equivalent to '{ List(1, 2, 3) }
71+
* ```
72+
*/
73+
class D { }
74+
5775
trait Quotes {
5876
val reflect: reflectModule = ???
5977
trait reflectModule { self: reflect.type =>
@@ -65,4 +83,4 @@ trait Quotes {
6583
*/
6684
def a = 3
6785
}
68-
}
86+
}

scaladoc/src/dotty/tools/scaladoc/snippets/SnippetChecker.scala

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,42 @@ class SnippetChecker(val args: Scaladoc.Args)(using cctx: CompilerContext):
4444
lineOffset: SnippetChecker.LineOffset,
4545
sourceFile: SourceFile
4646
): Option[SnippetCompilationResult] = {
47-
if arg.flag != SCFlags.NoCompile then
48-
val wrapped = WrappedSnippet(
49-
snippet,
50-
data.map(_.packageName),
51-
data.fold(Nil)(_.classInfos),
52-
data.map(_.imports).getOrElse(Nil),
53-
lineOffset + data.fold(0)(_.position.line) + constantLineOffset,
54-
data.fold(0)(_.position.column) + constantColumnOffset
55-
)
56-
val res = compiler.compile(wrapped, arg, sourceFile)
57-
Some(res)
58-
else None
47+
arg.flag match
48+
case SCFlags.Compile | SCFlags.Fail =>
49+
val wrapped = WrappedSnippet(
50+
snippet,
51+
data.map(_.packageName),
52+
data.fold(Nil)(_.classInfos),
53+
data.map(_.imports).getOrElse(Nil),
54+
lineOffset + data.fold(0)(_.position.line) + constantLineOffset,
55+
data.fold(0)(_.position.column) + constantColumnOffset
56+
)
57+
val res = compiler.compile(wrapped, arg, sourceFile)
58+
Some(res)
59+
case SCFlags.MacroCompile =>
60+
val wrapped = WrappedSnippet(
61+
snippet,
62+
data.map(_.packageName),
63+
data.map(_.imports).getOrElse(Nil),
64+
lineOffset + data.fold(0)(_.position.line) + constantLineOffset,
65+
data.fold(0)(_.position.column) + constantColumnOffset
66+
)
67+
val res = compiler.compile(wrapped, arg, sourceFile)
68+
Some(res)
69+
case SCFlags.UsingQuotes =>
70+
val wrapped = WrappedSnippet(
71+
snippet,
72+
data.map(_.packageName),
73+
data.fold(Nil)(_.classInfos),
74+
data.map(_.imports).getOrElse(Nil),
75+
lineOffset + data.fold(0)(_.position.line) + constantLineOffset,
76+
data.fold(0)(_.position.column) + constantColumnOffset,
77+
true
78+
)
79+
val res = compiler.compile(wrapped, arg, sourceFile)
80+
Some(res)
81+
case SCFlags.NoCompile => None
82+
5983
}
6084

6185
object SnippetChecker:

scaladoc/src/dotty/tools/scaladoc/snippets/SnippetCompilerArgs.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ import java.nio.file.Path
66
case class SnippetCompilerArg(flag: SCFlags):
77
def overrideFlag(f: SCFlags): SnippetCompilerArg = copy(flag = f)
88

9-
sealed trait SCFlags(val flagName: String)
10-
11-
object SCFlags:
12-
case object Compile extends SCFlags("compile")
13-
case object NoCompile extends SCFlags("nocompile")
14-
case object Fail extends SCFlags("fail")
15-
16-
def values: Seq[SCFlags] = Seq(Compile, NoCompile, Fail)
9+
enum SCFlags(val flagName: String):
10+
case Compile extends SCFlags("compile")
11+
case MacroCompile extends SCFlags("macrocompile")
12+
case UsingQuotes extends SCFlags("usingquotes")
13+
case NoCompile extends SCFlags("nocompile")
14+
case Fail extends SCFlags("fail")
1715

1816
case class SnippetCompilerArgs(scFlags: PathBased[SCFlags], defaultFlag: SCFlags):
1917
def get(member: Member): SnippetCompilerArg =
@@ -41,6 +39,8 @@ object SnippetCompilerArgs:
4139
|
4240
|Available flags:
4341
|compile - Enables snippet checking.
42+
|macrocompile - Enables snippet checking for macros.
43+
|usingquotes - Enables checking snippet additionally wrapped in `scala.quoted.Quotes` impilicit scope.
4444
|nocompile - Disables snippet checking.
4545
|fail - Enables snippet checking, asserts that snippet doesn't compile.
4646
|

scaladoc/src/dotty/tools/scaladoc/snippets/WrappedSnippet.scala

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,52 @@ object WrappedSnippet:
1010

1111
val indent: Int = 2
1212

13-
def apply(str: String): WrappedSnippet =
14-
val baos = new ByteArrayOutputStream()
15-
val ps = new PrintStream(baos)
16-
ps.startHide()
17-
ps.println("package snippets")
18-
ps.println("object Snippet {")
19-
ps.endHide()
20-
str.split('\n').foreach(ps.printlnWithIndent(indent, _))
21-
ps.startHide()
22-
ps.println("}")
23-
ps.endHide()
24-
WrappedSnippet(baos.toString, 0, 0, indent + 2 /*Hide tokens*/, indent)
13+
def apply(
14+
str: String,
15+
packageName: Option[String],
16+
imports: List[String],
17+
outerLineOffset: Int,
18+
outerColumnOffset: Int
19+
): WrappedSnippet =
20+
apply(str, packageName, Nil, imports, outerLineOffset, outerColumnOffset)
2521

2622
def apply(
2723
str: String,
2824
packageName: Option[String],
2925
classInfos: Seq[SnippetCompilerData.ClassInfo],
3026
imports: List[String],
3127
outerLineOffset: Int,
32-
outerColumnOffset: Int
28+
outerColumnOffset: Int,
29+
usingQuotes: Boolean = false
3330
): WrappedSnippet =
3431
val baos = new ByteArrayOutputStream()
3532
val ps = new PrintStream(baos)
3633
ps.startHide()
3734
ps.println(s"package ${packageName.getOrElse("snippets")}")
3835
imports.foreach(i => ps.println(s"import $i"))
39-
val notEmptyClassInfos = if classInfos.isEmpty then Seq(SnippetCompilerData.ClassInfo(None, Nil, None)) else classInfos
40-
notEmptyClassInfos.zipWithIndex.foreach { (info, i) =>
41-
ps.printlnWithIndent(indent * i, s"trait Snippet$i${info.generics.getOrElse("")} { ${info.tpe.fold("")(cn => s"self: $cn =>")}")
42-
info.names.foreach{ name =>
43-
ps.printlnWithIndent(indent * i + indent, s"val $name = self")
36+
val classInfoSize = if classInfos.isEmpty then 1 else classInfos.length + (if usingQuotes then 1 else 0)
37+
if classInfos.isEmpty then
38+
ps.println("object Snippet {")
39+
else
40+
classInfos.zipWithIndex.foreach { (info, i) =>
41+
ps.printlnWithIndent(indent * i, s"trait Snippet$i${info.generics.getOrElse("")} { ${info.tpe.fold("")(cn => s"self: $cn =>")}")
42+
info.names.foreach{ name =>
43+
ps.printlnWithIndent(indent * i + indent, s"val $name = self")
44+
}
4445
}
45-
}
46+
if usingQuotes then
47+
ps.printlnWithIndent(classInfos.length * indent, "def f(using Quotes) = {")
4648
ps.endHide()
47-
str.split('\n').foreach(ps.printlnWithIndent(notEmptyClassInfos.size * indent, _))
49+
str.split('\n').foreach(ps.printlnWithIndent(classInfoSize * indent, _))
4850
ps.startHide()
49-
(0 to notEmptyClassInfos.size -1).reverse.foreach( i => ps.printlnWithIndent(i * indent, "}"))
51+
(0 to classInfoSize -1).reverse.foreach( i => ps.printlnWithIndent(i * indent, "}"))
5052
ps.endHide()
5153
WrappedSnippet(
5254
baos.toString,
5355
outerLineOffset,
5456
outerColumnOffset,
55-
notEmptyClassInfos.size + notEmptyClassInfos.flatMap(_.names).size + packageName.size + 2 /*Hide tokens*/,
56-
notEmptyClassInfos.size * indent
57+
classInfoSize + classInfos.flatMap(_.names).size + packageName.size + 2 /*Hide tokens*/,
58+
classInfoSize * indent
5759
)
5860

5961
extension (ps: PrintStream)

0 commit comments

Comments
 (0)