Skip to content

Commit 7eba9a7

Browse files
[scaladoc] Allow to additional scalacOptions in Markdown code snippets (#24755)
Extracted from #24734 Adds support for `sc-opts:` attribute that can be set in Markdown code snippets, allowing to pass additioanl arguments to snippet compiler. This would allow us in #24734 to correctlly document behaviour of snippets producing error codes that require additional compiler options to be activated. Example: ensure that `-Werror` makes given code to actually fail which can be checked with `sc:fail`, ``` ```scala sc:fail sc-opts:-Werror,-explain def exampleShouldError(input: Option[String]): Unit = input match case Some("foo") => ??? ```. ```
1 parent c7c3170 commit 7eba9a7

File tree

7 files changed

+45
-9
lines changed

7 files changed

+45
-9
lines changed

scaladoc-testcases/docs/_docs/index.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,14 @@ val renderer: Renderer = Renderer()
2222
extension (x: Self) def combine(y: Self): Self
2323
```
2424

25+
```scala sc:fail sc-opts:-Werror:true
26+
def exampleShouldError(input: Option[String]): Unit =
27+
input match
28+
case Some("foo") => ???
29+
```
30+
31+
```scala sc:compile sc-opts:-Werror:false
32+
def exampleShouldWarn(input: Option[String]): Unit =
33+
input match
34+
case Some("foo") => ???
35+
```

scaladoc/src/dotty/tools/scaladoc/site/templates.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ case class TemplateFile(
8181
val path = Some(Paths.get(file.getAbsolutePath))
8282
val pathBasedArg = ssctx.snippetCompilerArgs.get(path)
8383
val sourceFile = dotty.tools.dotc.util.SourceFile(dotty.tools.io.AbstractFile.getFile(path.get), scala.io.Codec.UTF8)
84-
(str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SCFlags]) => {
85-
val arg = argOverride.fold(pathBasedArg)(pathBasedArg.overrideFlag(_))
84+
(str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SnippetCompilerArg]) => {
85+
val arg = argOverride.fold(pathBasedArg)(pathBasedArg.merge(_))
8686
val compilerData = SnippetCompilerData(
8787
"staticsitesnippet",
8888
SnippetCompilerData.Position(configOffset - 1, 0)

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ object FlexmarkSnippetProcessor:
2121
val lineOffset = node.getStartLineNumber + preparsed.fold(0)(_.strippedLinesBeforeNo)
2222
val info = node.getInfo.toString.split(" ")
2323
if info.contains("scala") then {
24-
val argOverride = info
24+
val flagOverride = info
2525
.find(_.startsWith("sc:"))
2626
.map(_.stripPrefix("sc:"))
2727
.map(SCFlagsParser.parse)
@@ -34,6 +34,19 @@ object FlexmarkSnippetProcessor:
3434
)
3535
None
3636
})
37+
38+
val scalacOptions: Seq[String] = info
39+
.toIndexedSeq
40+
.filter(_.startsWith("sc-opts:"))
41+
.flatMap(_.stripPrefix("sc-opts:").split(",").map(_.trim).toSeq)
42+
43+
val argOverride: Option[SnippetCompilerArg] =
44+
(flagOverride, scalacOptions) match {
45+
case (None, Seq()) => None
46+
case (Some(flag), opts) => Some(SnippetCompilerArg(flag, opts))
47+
case (None, opts) => Some(SnippetCompilerArg(SCFlags.Compile, opts))
48+
}
49+
3750
val id = info
3851
.find(_.startsWith("sc-name:"))
3952
.map(_.stripPrefix("sc-name:"))

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,4 @@ class SnippetChecker(val args: Scaladoc.Args)(using cctx: CompilerContext):
5959

6060
object SnippetChecker:
6161
type LineOffset = Int
62-
type SnippetCheckingFunc = (String, LineOffset, Option[SCFlags]) => Option[SnippetCompilationResult]
62+
type SnippetCheckingFunc = (String, LineOffset, Option[SnippetCompilerArg]) => Option[SnippetCompilationResult]

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ class SnippetCompiler(
8686

8787
private def additionalMessages(wrappedSnippet: WrappedSnippet, arg: SnippetCompilerArg, sourceFile: SourceFile, context: Context): Seq[SnippetCompilerMessage] = {
8888
Option.when(arg.flag == SCFlags.Fail && !context.reporter.hasErrors)(
89-
SnippetCompilerMessage(None, "Snippet should not compile but compiled successfully", MessageLevel.Error)
89+
SnippetCompilerMessage(
90+
Some(Position(SourcePosition(sourceFile, NoSpan), wrappedSnippet.outerLineOffset)),
91+
"Snippet should not compile but compiled successfully", MessageLevel.Error)
9092
).toList
9193
}
9294

@@ -100,12 +102,19 @@ class SnippetCompiler(
100102
arg: SnippetCompilerArg,
101103
sourceFile: SourceFile
102104
): SnippetCompilationResult = {
103-
val context = SnippetDriver.currentCtx.fresh
105+
val baseContext = SnippetDriver.currentCtx.fresh
104106
.setSetting(
105107
SnippetDriver.currentCtx.settings.outputDir,
106108
target
107109
)
108110
.setReporter(new StoreReporter)
111+
val context =
112+
if arg.scalacOptions.isEmpty then baseContext
113+
else
114+
val args = arg.scalacOptions.toArray
115+
SnippetDriver.setup(args, baseContext) match
116+
case Some((_, ctx)) => ctx
117+
case None => baseContext
109118
val run = newRun(using context)
110119
run.compileFromStrings(List(wrappedSnippet.snippet))
111120

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ package snippets
33

44
import java.nio.file.Path
55

6-
case class SnippetCompilerArg(flag: SCFlags):
6+
case class SnippetCompilerArg(flag: SCFlags, scalacOptions: Seq[String] = Seq.empty):
77
def overrideFlag(f: SCFlags): SnippetCompilerArg = copy(flag = f)
8+
def withScalacOptions(opts: Seq[String]): SnippetCompilerArg = copy(scalacOptions = scalacOptions ++ opts)
9+
def merge(other: SnippetCompilerArg): SnippetCompilerArg =
10+
SnippetCompilerArg(other.flag, scalacOptions ++ other.scalacOptions)
811

912
enum SCFlags(val flagName: String):
1013
case Compile extends SCFlags("compile")

scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ abstract class MarkupConversion[T](val repr: Repr)(using dctx: DocContext) {
137137
val scDataCollector = SnippetCompilerDataCollector[qctx.type](qctx)
138138
val data = scDataCollector.getSnippetCompilerData(s, s)
139139
val sourceFile = scDataCollector.getSourceFile(s)
140-
(str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SCFlags]) => {
141-
val arg = argOverride.fold(pathBasedArg)(pathBasedArg.overrideFlag(_))
140+
(str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SnippetCompilerArg]) => {
141+
val arg = argOverride.fold(pathBasedArg)(pathBasedArg.merge(_))
142142
val res = snippetChecker.checkSnippet(str, Some(data), arg, lineOffset, sourceFile)
143143
res.filter(r => !r.isSuccessful).foreach(_.reportMessages()(using compilerContext))
144144
res

0 commit comments

Comments
 (0)