Skip to content

Commit 937154c

Browse files
authored
Merge pull request #7 from pikinier20/static-site-snippets
Run snippet compiler on static sites
2 parents 0f870aa + eda1216 commit 937154c

22 files changed

+417
-174
lines changed

docs/css/dottydoc.css

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,18 +180,6 @@ h5:hover a.anchor:hover {
180180
font-family: var(--font-family-monospace);
181181
}
182182

183-
/* code */
184-
pre, code {
185-
font-variant-ligatures: none;
186-
}
187-
pre {
188-
padding: 0;
189-
font-size: 13px;
190-
background: var(--pre-bg);
191-
border-radius: 2px;
192-
border: 1px solid rgba(0, 0, 0, 0.1);
193-
}
194-
195183
/* admonitions */
196184
blockquote {
197185
padding: 0 1em;

project/Build.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,8 +1651,8 @@ object Build {
16511651
s"docs=github://lampepfl/dotty/master#docs",
16521652
"-doc-root-content", docRootFile.toString,
16531653
"-snippet-compiler:" +
1654-
s"$dottyLibRoot/scala/quoted=nocompile," +
1655-
s"$dottyLibRoot=compile",
1654+
s"$dottyLibRoot=compile," +
1655+
"docs=compile",
16561656
"-Ydocument-synthetic-types"
16571657
)
16581658
))
@@ -1665,6 +1665,7 @@ object Build {
16651665
"scaladoc/output/testcases",
16661666
"master",
16671667
Seq(
1668+
"-siteroot", "scaladoc-testcases/docs",
16681669
"-snippet-compiler-debug"
16691670
)
16701671
)

scaladoc-testcases/docs/docs/index.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
3+
4+
---
5+
6+
```scala sc:compile
7+
2 + List(0)
8+
```
9+
10+
```scala sc:compile
11+
new snippetCompiler.Snippet0 { }
12+
```
13+

scaladoc-testcases/src/tests/snippetCompilerTest.scala

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ package snippetCompiler
2727
* val d: Long = "asd"
2828
* ```
2929
*
30-
* ```scala sc:failing
30+
* ```scala sc:fail
3131
* def a = 2
3232
* val x = 1 + List()
3333
* a
3434
* ```
3535
*
36-
* ```scala sc:failing
36+
* ```scala sc:fail
3737
* def a = 2
3838
* ```
3939
*
@@ -42,12 +42,83 @@ package snippetCompiler
4242
* a()
4343
* ```
4444
*/
45-
class A { }
45+
class A {
46+
trait B
47+
val a = new B {
48+
/**
49+
* ```scala sc:compile
50+
* 2 + List()
51+
* ```
52+
*
53+
*/
54+
def a = 3
55+
}
56+
}
4657

4758
/**
48-
*
4959
* ```scala sc:compile
5060
* val c: Int = 4.5
5161
* ```
5262
*/
53-
class B { }
63+
class B { }
64+
65+
trait Quotes {
66+
val reflect: reflectModule = ???
67+
trait reflectModule { self: reflect.type =>
68+
/**
69+
* ```scala sc:compile
70+
* 2 + List()
71+
* ```
72+
*
73+
*/
74+
def a = 3
75+
}
76+
}
77+
78+
trait Quotes2[A] {
79+
val r1: r1Module[_] = ???
80+
trait r1Module[A] {
81+
type X
82+
object Y {
83+
/**
84+
* ```scala sc:compile
85+
* 2 + List()
86+
* ```
87+
*
88+
*/
89+
type YY
90+
}
91+
val z: zModule = ???
92+
trait zModule {
93+
/**
94+
* ```scala sc:compile
95+
* 2 + List()
96+
* ```
97+
*
98+
*/
99+
type ZZ
100+
}
101+
}
102+
object r2 {
103+
type X
104+
object Y {
105+
/**
106+
* ```scala sc:compile
107+
* 2 + List()
108+
* ```
109+
*
110+
*/
111+
type YY
112+
}
113+
val z: zModule = ???
114+
trait zModule {
115+
/**
116+
* ```scala sc:compile
117+
* 2 + List()
118+
* ```
119+
*
120+
*/
121+
type ZZ
122+
}
123+
}
124+
}

scaladoc/resources/dotty_res/styles/scalastyle.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ code {
9393
padding: 0 .3em;
9494
}
9595
pre {
96+
overflow: visible;
9697
scrollbar-width: thin;
9798
margin: 0px;
9899
}

scaladoc/src/dotty/tools/scaladoc/DocContext.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,15 @@ case class DocContext(args: Scaladoc.Args, compilerContext: CompilerContext):
7373

7474
lazy val snippetCompilerArgs = snippets.SnippetCompilerArgs.load(args.snippetCompiler, args.snippetCompilerDebug)(using compilerContext)
7575

76+
lazy val snippetChecker = snippets.SnippetChecker(args.classpath, args.tastyDirs)
77+
7678
lazy val staticSiteContext = args.docsRoot.map(path => StaticSiteContext(
7779
File(path).getAbsoluteFile(),
7880
args,
79-
sourceLinks
81+
sourceLinks,
82+
snippetCompilerArgs,
83+
snippetChecker
8084
)(using compilerContext))
8185

86+
8287
val externalDocumentationLinks = args.externalMappings

scaladoc/src/dotty/tools/scaladoc/api.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,11 +236,11 @@ case class TastyMemberSource(path: java.nio.file.Path, lineNumber: Int)
236236

237237
object SnippetCompilerData:
238238
case class Position(line: Int, column: Int)
239+
case class ClassInfo(tpe: Option[String], names: Seq[String], generics: Option[String])
239240

240241
case class SnippetCompilerData(
241242
packageName: String,
242-
classType: Option[String],
243-
classGenerics: Option[String],
243+
classInfos: Seq[SnippetCompilerData.ClassInfo],
244244
imports: List[String],
245245
position: SnippetCompilerData.Position
246246
)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ case class LoadedTemplate(
5151
("site" -> (getMap("site") + ("posts" -> posts))) + ("urls" -> sourceLinks.toMap) +
5252
("page" -> (getMap("page") + ("title" -> templateFile.title)))
5353

54-
templateFile.resolveInner(RenderingContext(updatedSettings, ctx.layouts))
54+
templateFile.resolveInner(RenderingContext(updatedSettings, ctx.layouts))(using ctx)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ import collection.JavaConverters._
1313
class StaticSiteContext(
1414
val root: File,
1515
val args: Scaladoc.Args,
16-
val sourceLinks: SourceLinks)(using val outerCtx: CompilerContext):
16+
val sourceLinks: SourceLinks,
17+
val snippetCompilerArgs: snippets.SnippetCompilerArgs,
18+
val snippetChecker: snippets.SnippetChecker)(using val outerCtx: CompilerContext):
1719

1820
var memberLinkResolver: String => Option[DRI] = _ => None
1921

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ val defaultMarkdownOptions: DataHolder =
3636
EmojiExtension.create(),
3737
YamlFrontMatterExtension.create(),
3838
StrikethroughExtension.create(),
39-
WikiLinkExtension.create()
39+
WikiLinkExtension.create(),
40+
tasty.comments.markdown.SnippetRenderingExtension
4041
))
4142

4243
def emptyTemplate(file: File, title: String): TemplateFile = TemplateFile(
@@ -48,7 +49,8 @@ def emptyTemplate(file: File, title: String): TemplateFile = TemplateFile(
4849
title = title,
4950
hasFrame = true,
5051
resources = List.empty,
51-
layout = None
52+
layout = None,
53+
configOffset = 0
5254
)
5355

5456
final val ConfigSeparator = "---"
@@ -106,6 +108,7 @@ def loadTemplateFile(file: File): TemplateFile = {
106108
title = stringSetting(allSettings, "title").getOrElse(name),
107109
hasFrame = !stringSetting(allSettings, "hasFrame").contains("false"),
108110
resources = (listSetting(allSettings, "extraCSS") ++ listSetting(allSettings, "extraJS")).flatten.toList,
109-
layout = stringSetting(allSettings, "layout")
111+
layout = stringSetting(allSettings, "layout"),
112+
configOffset = config.size
110113
)
111114
}

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

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools.scaladoc
22
package site
33

44
import java.io.File
5-
import java.nio.file.Files
5+
import java.nio.file.{Files, Paths}
66

77
import com.vladsch.flexmark.ext.anchorlink.AnchorLinkExtension
88
import com.vladsch.flexmark.ext.autolink.AutolinkExtension
@@ -18,6 +18,7 @@ import liqp.Template
1818
import scala.collection.JavaConverters._
1919

2020
import scala.io.Source
21+
import dotty.tools.scaladoc.snippets._
2122

2223
case class RenderingContext(
2324
properties: Map[String, Object],
@@ -52,10 +53,32 @@ case class TemplateFile(
5253
hasFrame: Boolean,
5354
resources: List[String],
5455
layout: Option[String],
56+
configOffset: Int
5557
):
5658
def isIndexPage() = file.isFile && (file.getName == "index.md" || file.getName == "index.html")
5759

58-
private[site] def resolveInner(ctx: RenderingContext): ResolvedPage =
60+
private[site] def resolveInner(ctx: RenderingContext)(using ssctx: StaticSiteContext): ResolvedPage =
61+
62+
lazy val snippetCheckingFunc: SnippetChecker.SnippetCheckingFunc =
63+
val path = Some(Paths.get(file.getAbsolutePath))
64+
val pathBasedArg = ssctx.snippetCompilerArgs.get(path)
65+
(str: String, lineOffset: SnippetChecker.LineOffset, argOverride: Option[SCFlags]) => {
66+
val arg = argOverride.fold(pathBasedArg)(pathBasedArg.overrideFlag(_))
67+
val compilerData = SnippetCompilerData(
68+
"staticsitesnippet",
69+
Seq(SnippetCompilerData.ClassInfo(None, Nil, None)),
70+
Nil,
71+
SnippetCompilerData.Position(configOffset - 1, 0)
72+
)
73+
ssctx.snippetChecker.checkSnippet(str, Some(compilerData), arg, lineOffset).collect {
74+
case r: SnippetCompilationResult if !r.isSuccessful =>
75+
val msg = s"In static site (${file.getAbsolutePath}):\n${r.getSummary}"
76+
report.error(msg)(using ssctx.outerCtx)
77+
r
78+
case r => r
79+
}
80+
}
81+
5982
if (ctx.resolving.contains(file.getAbsolutePath))
6083
throw new RuntimeException(s"Cycle in templates involving $file: ${ctx.resolving}")
6184

@@ -74,10 +97,13 @@ case class TemplateFile(
7497
val rendered = Template.parse(this.rawCode).render(mutableProperties)
7598
// We want to render markdown only if next template is html
7699
val code = if (isHtml || layoutTemplate.exists(!_.isHtml)) rendered else
100+
// Snippet compiler currently supports markdown only
77101
val parser: Parser = Parser.builder(defaultMarkdownOptions).build()
78-
HtmlRenderer.builder(defaultMarkdownOptions).build().render(parser.parse(rendered))
102+
val parsedMd = parser.parse(rendered)
103+
val processed = FlexmarkSnippetProcessor.processSnippets(parsedMd, ssctx.snippetCompilerArgs.debug, snippetCheckingFunc)(using ssctx.outerCtx)
104+
HtmlRenderer.builder(defaultMarkdownOptions).build().render(processed)
79105

80106
layoutTemplate match
81107
case None => ResolvedPage(code, resources ++ ctx.resources)
82108
case Some(layoutTemplate) =>
83-
layoutTemplate.resolveInner(ctx.nest(code, file, resources))
109+
layoutTemplate.resolveInner(ctx.nest(code, file, resources))
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package dotty.tools.scaladoc
2+
package snippets
3+
4+
import com.vladsch.flexmark.util.{ast => mdu, sequence}
5+
import com.vladsch.flexmark.{ast => mda}
6+
import com.vladsch.flexmark.formatter.Formatter
7+
import com.vladsch.flexmark.util.options.MutableDataSet
8+
import collection.JavaConverters._
9+
10+
import dotty.tools.scaladoc.tasty.comments.markdown.ExtendedFencedCodeBlock
11+
12+
object FlexmarkSnippetProcessor:
13+
def processSnippets(root: mdu.Node, debug: Boolean, checkingFunc: => SnippetChecker.SnippetCheckingFunc)(using CompilerContext): mdu.Node = {
14+
lazy val cf: SnippetChecker.SnippetCheckingFunc = checkingFunc
15+
16+
val nodes = root.getDescendants().asScala.collect {
17+
case fcb: mda.FencedCodeBlock => fcb
18+
}.toList
19+
20+
nodes.foreach { node =>
21+
val snippet = node.getContentChars.toString
22+
val lineOffset = node.getStartLineNumber
23+
val info = node.getInfo.toString.split(" ")
24+
if info.contains("scala") then {
25+
val argOverride =
26+
info
27+
.find(_.startsWith("sc:"))
28+
.map(_.stripPrefix("sc:"))
29+
.map(SCFlagsParser.parse)
30+
.flatMap(_ match {
31+
case Right(flags) => Some(flags)
32+
case Left(error) =>
33+
report.warning(
34+
s"""|Error occured during parsing flags in snippet:
35+
|$error""".stripMargin
36+
)
37+
None
38+
})
39+
val snippetCompilationResult = cf(snippet, lineOffset, argOverride) match {
40+
case result@Some(SnippetCompilationResult(wrapped, _, _, _)) if debug =>
41+
val s = sequence.BasedSequence.EmptyBasedSequence()
42+
.append(wrapped)
43+
.append(sequence.BasedSequence.EOL)
44+
val content = mdu.BlockContent()
45+
content.add(s, 0)
46+
node.setContent(content)
47+
result
48+
case result => result
49+
}
50+
51+
node.insertBefore(new ExtendedFencedCodeBlock(node, snippetCompilationResult))
52+
node.unlink()
53+
}
54+
}
55+
56+
root
57+
}

0 commit comments

Comments
 (0)