Skip to content

Commit f250e6a

Browse files
committed
Further implementation of snippet compiler. Add package name and self type to pass context
1 parent 46ddbe9 commit f250e6a

File tree

7 files changed

+88
-21
lines changed

7 files changed

+88
-21
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,5 @@ extension (s: Signature)
233233
}.mkString
234234

235235
case class TastyMemberSource(val path: java.nio.file.Path, val lineNumber: Int)
236+
237+
case class SnippetCompilerData(val packageName: String, val classType: Option[String], val classGenerics: Option[String], val imports: List[String])

scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import java.nio.file.Files
1414
import java.nio.file.FileVisitOption
1515
import java.io.File
1616

17+
import dotty.tools.scaladoc.snippets._
18+
1719
case class Page(link: Link, content: Member | ResolvedTemplate | String, children: Seq[Page]):
1820
def withNewChildren(newChildren: Seq[Page]) = copy(children = children ++ newChildren)
1921

@@ -26,6 +28,7 @@ case class Page(link: Link, content: Member | ResolvedTemplate | String, childre
2628
class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx: DocContext)
2729
extends SiteRenderer, Resources, Locations, Writer:
2830
private val args = summon[DocContext].args
31+
private val snippetChecker = SnippetChecker()
2932
val staticSite = summon[DocContext].staticSiteContext
3033

3134
val effectiveMembers = members
@@ -75,7 +78,7 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx
7578
def link(dri: DRI): Option[String] =
7679
Some(pathToPage(currentDri, dri)).filter(_ != UnresolvedLocationLink)
7780

78-
MemberRenderer(signatureRenderer).fullMember(m)
81+
MemberRenderer(signatureRenderer, snippetChecker).fullMember(m)
7982
case t: ResolvedTemplate => siteContent(page.link.dri, t)
8083
case a: String => raw(a)
8184

@@ -119,6 +122,7 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx
119122
def render(): Unit =
120123
val renderedResources = renderResources()
121124
val sites = allPages.map(renderPage(_, Vector.empty))
125+
println(snippetChecker.summary)
122126

123127
def mkHead(page: Page): AppliedTag =
124128
val resources = page.content match

scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import dotty.tools.scaladoc.tasty.comments.markdown.DocFlexmarkRenderer
99
import com.vladsch.flexmark.util.ast.{Node => MdNode}
1010
import dotty.tools.scaladoc.tasty.comments.wiki.WikiDocElement
1111
import translators._
12+
import dotty.tools.scaladoc.snippets._
1213

13-
class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) extends DocRender(signatureRenderer):
14+
class MemberRenderer(signatureRenderer: SignatureRenderer, snippetChecker: SnippetChecker)(using DocContext) extends DocRender(signatureRenderer, snippetChecker):
1415
import signatureRenderer._
1516

1617
def doc(m: Member): Seq[AppliedTag] = m.docs.fold(Nil)(d => Seq(renderDocPart(d.body)(using m)))

scaladoc/src/dotty/tools/scaladoc/renderers/WikiDocRenderer.scala

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,17 @@ import dotty.tools.scaladoc.tasty.comments.wiki.WikiDocElement
88
import dotty.tools.scaladoc.tasty.comments.markdown.DocFlexmarkRenderer
99
import dotty.tools.scaladoc.snippets._
1010

11-
class DocRender(signatureRenderer: SignatureRenderer)(using DocContext):
12-
13-
private val snippetChecker = SnippetChecker()
11+
class DocRender(signatureRenderer: SignatureRenderer, snippetChecker: SnippetChecker)(using DocContext):
1412

1513
private val snippetCheckingFunc: Member => String => Unit =
1614
(m: Member) => {
1715
(str: String) => {
18-
snippetChecker.checkSnippet(str) match {
19-
case r @ SnippetCompilationResult(None, _) =>
20-
println(s"In member ${m.name}:")
21-
println(r.getSummary)
22-
case _ =>
23-
}
16+
snippetChecker.checkSnippet(str, m.docs.map(_.snippetCompilerData)) match {
17+
case r @ SnippetCompilationResult(None, _) =>
18+
println(s"In member ${m.name}:")
19+
println(r.getSummary)
20+
case _ =>
21+
}
2422
}
2523
}
2624

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,25 @@ class SnippetChecker(
77
private val compiler: SnippetCompiler = SnippetCompiler(),
88
private val wrapper: SnippetWrapper = SnippetWrapper()
99
):
10-
def checkSnippet(snippet: String): SnippetCompilationResult = {
11-
val wrapped = wrapper.wrap(snippet)
12-
compiler.compile(wrapped)
13-
}
10+
var warningsCount = 0
11+
var errorsCount = 0
12+
13+
def checkSnippet(snippet: String, data: Option[SnippetCompilerData]): SnippetCompilationResult = {
14+
val wrapped = wrapper.wrap(
15+
snippet,
16+
data.map(_.packageName),
17+
data.flatMap(_.classType),
18+
data.flatMap(_.classGenerics),
19+
data.map(_.imports).getOrElse(Nil)
20+
)
21+
val res = compiler.compile(wrapped)
22+
if !res.messages.filter(_.level == MessageLevel.Error).isEmpty then errorsCount = errorsCount + 1
23+
if !res.messages.filter(_.level == MessageLevel.Warning).isEmpty then warningsCount = warningsCount + 1
24+
res
25+
}
26+
27+
def summary: String = s"""
28+
|Snippet compiler summary:
29+
| Found $warningsCount warnings
30+
| Found $errorsCount errors
31+
|""".stripMargin

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import java.io.ByteArrayOutputStream
55
import java.io.PrintStream
66

77
class SnippetWrapper:
8-
extension (ps: PrintStream) def printlnWithIndent(indent: Int, str: String) =
8+
extension (ps: PrintStream) private def printlnWithIndent(indent: Int, str: String) =
99
ps.println((" " * indent) + str)
1010
def wrap(str: String): String =
1111
val baos = new ByteArrayOutputStream()
@@ -16,6 +16,16 @@ class SnippetWrapper:
1616
ps.println("}")
1717
baos.toString
1818

19+
def wrap(str:String, packageName: Option[String], className: Option[String], classGenerics: Option[String], imports: List[String]) =
20+
val baos = new ByteArrayOutputStream()
21+
val ps = new PrintStream(baos)
22+
ps.println(s"package ${packageName.getOrElse("snippets")}")
23+
imports.foreach(i => ps.println(s"import $i"))
24+
ps.println(s"trait Snippet${classGenerics.getOrElse("")} { ${className.fold("")(cn => s"self: $cn =>")}")
25+
str.split('\n').foreach(ps.printlnWithIndent(2, _))
26+
ps.println("}")
27+
baos.toString
28+
1929
object SnippetWrapper:
20-
val lineOffset = 2
21-
val columnOffset = 2
30+
private val lineOffset = 2
31+
private val columnOffset = 2

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

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ case class Comment (
3939
groupNames: SortedMap[String, DocPart],
4040
groupPrio: SortedMap[String, Int],
4141
/** List of conversions to hide - containing e.g: `scala.Predef.FloatArrayOps` */
42-
hideImplicitConversions: List[DocPart]
42+
hideImplicitConversions: List[DocPart],
43+
snippetCompilerData: SnippetCompilerData
4344
)
4445

4546
case class PreparsedComment(
@@ -82,7 +83,7 @@ abstract class MarkupConversion[T](val repr: Repr)(using DocContext) {
8283
if repr == null then null.asInstanceOf[qctx.reflect.Symbol] else repr.sym
8384

8485
object SymOps extends SymOps[qctx.type](qctx)
85-
export SymOps.dri
86+
export SymOps._
8687

8788
def resolveLink(queryStr: String): DocLink =
8889
if SchemeUri.matches(queryStr) then DocLink.ToURL(queryStr)
@@ -116,6 +117,38 @@ abstract class MarkupConversion[T](val repr: Repr)(using DocContext) {
116117
case _ => None
117118
}
118119

120+
private def getSnippetCompilerData(sym: qctx.reflect.Symbol): SnippetCompilerData =
121+
val packageName = sym.packageName
122+
if !sym.isPackageDef then sym.tree match {
123+
case c: qctx.reflect.ClassDef =>
124+
import qctx.reflect._
125+
import dotty.tools.dotc
126+
given dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx
127+
val cSym = c.symbol.asInstanceOf[dotc.core.Symbols.ClassSymbol]
128+
129+
def createTypeConstructor(tpe: dotc.core.Types.Type, topLevel: Boolean = true): String = tpe match {
130+
case t @ dotc.core.Types.TypeBounds(upper, lower) => lower match {
131+
case l: dotc.core.Types.HKTypeLambda =>
132+
(if topLevel then "" else "?") + l.paramInfos.map(p => createTypeConstructor(p, false)).mkString("[",", ","]")
133+
case _ => (if topLevel then "" else "_")
134+
}
135+
}
136+
val classType =
137+
val ct = cSym.classInfo.selfType.show.replace(".this.",".")
138+
Some(ct)
139+
val classGenerics = Option.when(
140+
!cSym.typeParams.isEmpty
141+
)(
142+
cSym.typeParams.map(_.typeRef).map(t =>
143+
t.show +
144+
createTypeConstructor(t.asInstanceOf[dotc.core.Types.TypeRef].underlying)
145+
).mkString("[",", ","]")
146+
)
147+
SnippetCompilerData(packageName, classType, classGenerics, Nil)
148+
case _ => getSnippetCompilerData(sym.maybeOwner)
149+
} else SnippetCompilerData(packageName, None, None, Nil)
150+
151+
119152
final def parse(preparsed: PreparsedComment): Comment =
120153
val body = markupToDokkaCommentBody(stringToMarkup(preparsed.body))
121154
Comment(
@@ -138,7 +171,8 @@ abstract class MarkupConversion[T](val repr: Repr)(using DocContext) {
138171
groupDesc = filterEmpty(preparsed.groupDesc).view.mapValues(markupToDokka).to(SortedMap),
139172
groupNames = filterEmpty(preparsed.groupNames).view.mapValues(markupToDokka).to(SortedMap),
140173
groupPrio = preparsed.groupPrio,
141-
hideImplicitConversions = filterEmpty(preparsed.hideImplicitConversions).map(markupToDokka)
174+
hideImplicitConversions = filterEmpty(preparsed.hideImplicitConversions).map(markupToDokka),
175+
snippetCompilerData = getSnippetCompilerData(owner)
142176
)
143177
}
144178

0 commit comments

Comments
 (0)