Skip to content

Commit 78b7d49

Browse files
committed
Try not to use Reflection directly
We need to use it directly in MarkdownConverter for now (since there reflection comes from Repr rather then `QuoteContext`)
1 parent 6fc39bf commit 78b7d49

File tree

10 files changed

+159
-153
lines changed

10 files changed

+159
-153
lines changed

sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,11 +357,11 @@ object DottyPlugin extends AutoPlugin {
357357
}.value,
358358

359359
// Configuration for the doctool
360-
resolvers ++= Seq(
360+
resolvers ++= (if(useScala3doc.value) Nil else Seq(
361361
Resolver.jcenterRepo,
362362
Resolver.bintrayRepo("kotlin", "kotlin-dev"),
363363
Resolver.bintrayRepo("virtuslab", "dokka"),
364-
),
364+
)),
365365
useScala3doc := false,
366366
scala3docOptions := Nil,
367367
Compile / doc / scalacOptions := {

scala3doc/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Scala3doc (name subject to change) is the documentation tool for
44
[Dotty](https://github.com/lampepfl/dotty), which is scheduled to become
55
Scala 3. It's based on [Dokka](https://github.com/Kotlin/dokka), the
6-
documentation tool for Kotlin. It uses Tasty-Reflect to access definitions,
6+
documentation tool for Kotlin. It uses the TastyInspector to access definitions,
77
which is an officially supported way to access Dotty's perspective of a
88
codebase.
99

scala3doc/src/dotty/dokka/tasty/BasicSupport.scala

Lines changed: 4 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,12 @@ import org.jetbrains.dokka.links._
44
import org.jetbrains.dokka.model._
55
import collection.JavaConverters._
66
import dotty.dokka._
7-
import dotty.dokka.model.api.Visibility
8-
import dotty.dokka.model.api.VisibilityScope
9-
import dotty.dokka.model.api.Modifier
107
import dotty.dokka.model.api.Annotation
118

12-
13-
import scala.tasty.Reflection
14-
159
trait BasicSupport:
1610
self: TastyParser =>
17-
import reflect._
18-
19-
object SymOps extends SymOps[reflect.type](reflect)
11+
import qctx.reflect._
12+
object SymOps extends SymOps[qctx.reflect.type](qctx.reflect)
2013
export SymOps._
2114

2215
def parseAnnotation(annotTerm: Term): Annotation =
@@ -39,8 +32,8 @@ trait BasicSupport:
3932
Annotation(dri, params)
4033

4134

42-
extension (sym: reflect.Symbol):
43-
def documentation(using cxt: reflect.Context) = sym.documentation match
35+
extension (sym: Symbol):
36+
def documentation(using cxt: Context) = sym.documentation match
4437
case Some(comment) =>
4538
Map(sourceSet.getSourceSet -> parseComment(comment, sym.tree))
4639
case None =>
@@ -58,114 +51,5 @@ trait BasicSupport:
5851

5952
private val emptyDRI = DRI.Companion.getTopLevel
6053

61-
class SymOps[R <: Reflection](val r: R):
62-
import r._
63-
64-
given R = r
65-
66-
extension (sym: r.Symbol):
67-
def packageName(using ctx: Context): String =
68-
if (sym.isPackageDef) sym.fullName
69-
else sym.maybeOwner.packageName
70-
71-
def topLevelEntryName(using ctx: Context): Option[String] = if (sym.isPackageDef) None else
72-
if (sym.owner.isPackageDef) Some(sym.name) else sym.owner.topLevelEntryName
73-
74-
def getVisibility(): Visibility =
75-
import VisibilityScope._
76-
77-
def explicitScope(ownerType: TypeRepr): VisibilityScope =
78-
val moduleSym = ownerType.typeSymbol.companionModule
79-
if moduleSym.isNoSymbol
80-
then ExplicitTypeScope(ownerType.typeSymbol.name)
81-
else ExplicitModuleScope(moduleSym.name)
82-
83-
def implicitScope(ownerSym: Symbol): VisibilityScope =
84-
val moduleSym = ownerSym.companionModule
85-
if moduleSym.isNoSymbol
86-
then ImplicitTypeScope
87-
else ImplicitModuleScope
88-
89-
val visibilityFlags = (sym.flags.is(Flags.Private), sym.flags.is(Flags.Protected), sym.flags.is(Flags.Local))
90-
(sym.privateWithin, sym.protectedWithin, visibilityFlags) match
91-
case (Some(owner), None, _) => Visibility.Private(explicitScope(owner))
92-
case (None, Some(owner), _) => Visibility.Protected(explicitScope(owner))
93-
case (None, None, (true, false, _)) => Visibility.Private(implicitScope(sym.owner))
94-
case (None, None, (false, true, true)) => Visibility.Protected(ThisScope)
95-
case (None, None, (false, true, false)) => Visibility.Protected(implicitScope(sym.owner))
96-
case (None, None, (false, false, false)) => Visibility.Unrestricted
97-
case _ => throw new Exception(s"Visibility for symbol $sym cannot be determined")
98-
99-
// TODO: #49 Remove it after TASTY-Reflect release with published flag Extension
100-
def hackIsOpen: Boolean = {
101-
import dotty.tools.dotc
102-
given dotc.core.Contexts.Context = r.rootContext.asInstanceOf
103-
val symbol = sym.asInstanceOf[dotc.core.Symbols.Symbol]
104-
symbol.is(dotc.core.Flags.Open)
105-
}
106-
107-
// Order here determines order in documenation
108-
def getExtraModifiers(): Seq[Modifier] = Seq(
109-
Flags.Final -> Modifier.Final,
110-
Flags.Sealed -> Modifier.Sealed,
111-
Flags.Erased -> Modifier.Erased,
112-
Flags.Abstract -> Modifier.Abstract,
113-
Flags.Implicit -> Modifier.Implicit,
114-
Flags.Inline -> Modifier.Inline,
115-
Flags.Lazy -> Modifier.Lazy,
116-
Flags.Override -> Modifier.Override,
117-
Flags.Case -> Modifier.Case,
118-
).collect { case (flag, mod) if sym.flags.is(flag) => mod }
119-
++ (if(sym.hackIsOpen) Seq(Modifier.Open) else Nil)
120-
121-
def isHiddenByVisibility: Boolean =
122-
import VisibilityScope._
123-
124-
getVisibility() match
125-
case Visibility.Private(_) => true
126-
case Visibility.Protected(ThisScope | ImplicitModuleScope | _: ExplicitModuleScope) => true
127-
case _ => false
128-
129-
def shouldDocumentClasslike: Boolean = !isHiddenByVisibility
130-
&& !sym.flags.is(Flags.Synthetic)
131-
&& (!sym.flags.is(Flags.Case) || !sym.flags.is(Flags.Enum))
132-
&& !(sym.companionModule.flags.is(Flags.Given))
133-
134-
135-
def getCompanionSymbol: Option[Symbol] = Some(sym.companionClass).filter(_.exists)
136-
137-
def isCompanionObject: Boolean = sym.flags.is(Flags.Object) && sym.companionClass.exists
138-
139-
def isGiven: Boolean = sym.flags.is(Flags.Given)
140-
141-
def isExtensionMethod: Boolean = sym.flags.is(Flags.ExtensionMethod)
142-
143-
def isLeftAssoc(d: Symbol): Boolean = !d.name.endsWith(":")
144-
145-
def extendedSymbol: Option[ValDef] =
146-
Option.when(sym.isExtensionMethod)(
147-
if(isLeftAssoc(sym)) sym.tree.asInstanceOf[DefDef].paramss(0)(0)
148-
else sym.tree.asInstanceOf[DefDef].paramss(1)(0)
149-
)
150-
151-
// TODO #22 make sure that DRIs are unique plus probably reuse semantic db code?
152-
def dri: DRI =
153-
if sym == Symbol.noSymbol then emptyDRI else if sym.isValDef && sym.moduleClass.exists then sym.moduleClass.dri else
154-
val pointsTo =
155-
if (!sym.isTypeDef) PointingToDeclaration.INSTANCE
156-
else PointingToGenericParameters(sym.owner.typeMembers.indexOf(sym))
157-
158-
val method =
159-
if (sym.isDefDef) Some(sym)
160-
else if (sym.maybeOwner.isDefDef) Some(sym.owner)
161-
else None
16254

163-
new DRI(
164-
sym.packageName,
165-
sym.topLevelEntryName.orNull, // TODO do we need any of this fields?
166-
method.map(s => new org.jetbrains.dokka.links.Callable(s.name, null, Nil.asJava)).orNull,
167-
pointsTo, // TODO different targets?
168-
s"${sym.show}/${sym.signature.resultSig}/[${sym.signature.paramSigs.mkString("/")}]"
169-
)
17055

171-
private val emptyDRI = DRI.Companion.getTopLevel

scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import dotty.dokka.model.api.{Signature => DSignature, Link => DLink}
1717

1818
trait ClassLikeSupport:
1919
self: TastyParser =>
20-
import reflect._
20+
import qctx.reflect._
2121

2222
private val placeholderVisibility = Map(sourceSet.getSourceSet -> KotlinVisibility.Public.INSTANCE).asJava
2323
private val placeholderModifier = Map(sourceSet.getSourceSet -> KotlinModifier.Empty.INSTANCE).asJava
@@ -161,12 +161,12 @@ trait ClassLikeSupport:
161161
parseMethod(d, constructorWithoutParamLists(c), s => c.getParameterModifier(s))
162162
)
163163

164-
def parseClasslike(classDef: reflect.ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass = classDef match
164+
def parseClasslike(classDef: ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass = classDef match
165165
case c: ClassDef if classDef.symbol.flags.is(Flags.Object) => parseObject(c, signatureOnly)
166166
case c: ClassDef if classDef.symbol.flags.is(Flags.Enum) => parseEnum(c, signatureOnly)
167167
case clazz => DClass(classDef)(signatureOnly = signatureOnly)
168168

169-
def parseObject(classDef: reflect.ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass =
169+
def parseObject(classDef: ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass =
170170
DClass(classDef)(
171171
name = classDef.name.stripSuffix("$"),
172172
// All objects are final so we do not need final modifer!
@@ -175,7 +175,7 @@ trait ClassLikeSupport:
175175
)
176176

177177
// TODO check withNewExtras?
178-
def parseEnum(classDef: reflect.ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass =
178+
def parseEnum(classDef: ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass =
179179
val extraModifiers = classDef.symbol.getExtraModifiers().filter(_ != Modifier.Sealed).filter(_ != Modifier.Abstract)
180180
val companion = classDef.symbol.getCompanionSymbol.map(_.tree.asInstanceOf[ClassDef]).get
181181

scala3doc/src/dotty/dokka/tasty/PackageSupport.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import collection.JavaConverters._
1111

1212
trait PackageSupport:
1313
self: TastyParser =>
14-
import reflect._
14+
import qctx.reflect._
1515

1616
def parsePackage(pck: PackageClause): DPackage = {
1717
val name = extractPackageName(pck.pid.show)

scala3doc/src/dotty/dokka/tasty/ScalaDocSupport.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import dotty.dokka.ScalaTagWrapper
1010
import comments.{kt, dkk}
1111

1212
trait ScaladocSupport { self: TastyParser =>
13-
import reflect._
13+
import qctx.reflect._
1414

1515
def parseComment(
16-
commentNode: reflect.Documentation,
17-
tree: reflect.Tree
16+
commentNode: Documentation,
17+
tree: Tree
1818
): dkkd.DocumentationNode = {
1919
val preparsed =
2020
comments.Preparser.preparse(comments.Cleaner.clean(commentNode.raw))
@@ -32,9 +32,9 @@ trait ScaladocSupport { self: TastyParser =>
3232

3333
val parser = commentSyntax match {
3434
case CommentSyntax.Wiki =>
35-
comments.WikiCommentParser(comments.Repr(reflect)(tree.symbol))
35+
comments.WikiCommentParser(comments.Repr(qctx.reflect)(tree.symbol))
3636
case CommentSyntax.Markdown =>
37-
comments.MarkdownCommentParser(comments.Repr(reflect)(tree.symbol))
37+
comments.MarkdownCommentParser(comments.Repr(qctx.reflect)(tree.symbol))
3838
}
3939
val parsed = parser.parse(preparsed)
4040

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package dotty.dokka.tasty
2+
3+
import org.jetbrains.dokka.links._
4+
import org.jetbrains.dokka.model._
5+
import collection.JavaConverters._
6+
import dotty.dokka._
7+
import dotty.dokka.model.api.Visibility
8+
import dotty.dokka.model.api.VisibilityScope
9+
import dotty.dokka.model.api.Modifier
10+
import scala.tasty.Reflection
11+
12+
class SymOps[R <: Reflection](val r: R):
13+
import r._
14+
15+
given R = r
16+
extension (sym: r.Symbol):
17+
def packageName(using ctx: Context): String =
18+
if (sym.isPackageDef) sym.fullName
19+
else sym.maybeOwner.packageName
20+
21+
def topLevelEntryName(using ctx: Context): Option[String] = if (sym.isPackageDef) None else
22+
if (sym.owner.isPackageDef) Some(sym.name) else sym.owner.topLevelEntryName
23+
24+
def getVisibility(): Visibility =
25+
import VisibilityScope._
26+
27+
def explicitScope(ownerType: TypeRepr): VisibilityScope =
28+
val moduleSym = ownerType.typeSymbol.companionModule
29+
if moduleSym.isNoSymbol
30+
then ExplicitTypeScope(ownerType.typeSymbol.name)
31+
else ExplicitModuleScope(moduleSym.name)
32+
33+
def implicitScope(ownerSym: Symbol): VisibilityScope =
34+
val moduleSym = ownerSym.companionModule
35+
if moduleSym.isNoSymbol
36+
then ImplicitTypeScope
37+
else ImplicitModuleScope
38+
39+
val visibilityFlags = (sym.flags.is(Flags.Private), sym.flags.is(Flags.Protected), sym.flags.is(Flags.Local))
40+
(sym.privateWithin, sym.protectedWithin, visibilityFlags) match
41+
case (Some(owner), None, _) => Visibility.Private(explicitScope(owner))
42+
case (None, Some(owner), _) => Visibility.Protected(explicitScope(owner))
43+
case (None, None, (true, false, _)) => Visibility.Private(implicitScope(sym.owner))
44+
case (None, None, (false, true, true)) => Visibility.Protected(ThisScope)
45+
case (None, None, (false, true, false)) => Visibility.Protected(implicitScope(sym.owner))
46+
case (None, None, (false, false, false)) => Visibility.Unrestricted
47+
case _ => throw new Exception(s"Visibility for symbol $sym cannot be determined")
48+
49+
// TODO: #49 Remove it after TASTY-Reflect release with published flag Extension
50+
def hackIsOpen: Boolean = {
51+
import dotty.tools.dotc
52+
given dotc.core.Contexts.Context = r.rootContext.asInstanceOf
53+
val symbol = sym.asInstanceOf[dotc.core.Symbols.Symbol]
54+
symbol.is(dotc.core.Flags.Open)
55+
}
56+
57+
// Order here determines order in documenation
58+
def getExtraModifiers(): Seq[Modifier] = Seq(
59+
Flags.Final -> Modifier.Final,
60+
Flags.Sealed -> Modifier.Sealed,
61+
Flags.Erased -> Modifier.Erased,
62+
Flags.Abstract -> Modifier.Abstract,
63+
Flags.Implicit -> Modifier.Implicit,
64+
Flags.Inline -> Modifier.Inline,
65+
Flags.Lazy -> Modifier.Lazy,
66+
Flags.Override -> Modifier.Override,
67+
Flags.Case -> Modifier.Case,
68+
).collect { case (flag, mod) if sym.flags.is(flag) => mod }
69+
++ (if(sym.hackIsOpen) Seq(Modifier.Open) else Nil)
70+
71+
def isHiddenByVisibility: Boolean =
72+
import VisibilityScope._
73+
74+
getVisibility() match
75+
case Visibility.Private(_) => true
76+
case Visibility.Protected(ThisScope | ImplicitModuleScope | _: ExplicitModuleScope) => true
77+
case _ => false
78+
79+
def shouldDocumentClasslike: Boolean = !isHiddenByVisibility
80+
&& !sym.flags.is(Flags.Synthetic)
81+
&& (!sym.flags.is(Flags.Case) || !sym.flags.is(Flags.Enum))
82+
&& !(sym.companionModule.flags.is(Flags.Given))
83+
84+
85+
def getCompanionSymbol: Option[Symbol] = Some(sym.companionClass).filter(_.exists)
86+
87+
def isCompanionObject: Boolean = sym.flags.is(Flags.Object) && sym.companionClass.exists
88+
89+
def isGiven: Boolean = sym.flags.is(Flags.Given)
90+
91+
def isExtensionMethod: Boolean = sym.flags.is(Flags.ExtensionMethod)
92+
93+
def isLeftAssoc(d: Symbol): Boolean = !d.name.endsWith(":")
94+
95+
def extendedSymbol: Option[ValDef] =
96+
Option.when(sym.isExtensionMethod)(
97+
if(isLeftAssoc(sym)) sym.tree.asInstanceOf[DefDef].paramss(0)(0)
98+
else sym.tree.asInstanceOf[DefDef].paramss(1)(0)
99+
)
100+
101+
// TODO #22 make sure that DRIs are unique plus probably reuse semantic db code?
102+
def dri: DRI =
103+
if sym == Symbol.noSymbol then emptyDRI else if sym.isValDef && sym.moduleClass.exists then sym.moduleClass.dri else
104+
val pointsTo =
105+
if (!sym.isTypeDef) PointingToDeclaration.INSTANCE
106+
else PointingToGenericParameters(sym.owner.typeMembers.indexOf(sym))
107+
108+
val method =
109+
if (sym.isDefDef) Some(sym)
110+
else if (sym.maybeOwner.isDefDef) Some(sym.owner)
111+
else None
112+
113+
new DRI(
114+
sym.packageName,
115+
sym.topLevelEntryName.orNull, // TODO do we need any of this fields?
116+
method.map(s => new org.jetbrains.dokka.links.Callable(s.name, null, Nil.asJava)).orNull,
117+
pointsTo, // TODO different targets?
118+
s"${sym.show}/${sym.signature.resultSig}/[${sym.signature.paramSigs.mkString("/")}]"
119+
)
120+
121+
private val emptyDRI = DRI.Companion.getTopLevel

0 commit comments

Comments
 (0)