Skip to content

Commit 31566b7

Browse files
authored
Merge pull request #10334 from pikinier20/bugfixes-227
Scala3doc: Bugfixes related to symbol names and extension methods
2 parents 4265f08 + 01dcb59 commit 31566b7

9 files changed

+70
-29
lines changed

scala3doc/src/dotty/dokka/model/api/api.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ enum Modifier(val name: String, val prefix: Boolean):
4747
case Opaque extends Modifier("opaque", true)
4848
case Open extends Modifier("open", true)
4949

50-
case class ExtensionTarget(name: String, signature: Signature, dri: DRI)
50+
case class ExtensionTarget(name: String, signature: Signature, dri: DRI, position: Long)
5151
case class ImplicitConversion(from: DRI, to: DRI)
5252
trait ImplicitConversionProvider { def conversion: Option[ImplicitConversion] }
5353
trait Classlike

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

+14-14
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ trait ClassLikeSupport:
2929
object DClass:
3030
def apply[T >: DClass](classDef: ClassDef)(
3131
dri: DRI = classDef.symbol.dri,
32-
name: String = classDef.name,
32+
name: String = classDef.symbol.normalizedName,
3333
signatureOnly: Boolean = false,
3434
modifiers: Seq[Modifier] = classDef.symbol.getExtraModifiers(),
3535
): DClass =
@@ -108,7 +108,12 @@ trait ClassLikeSupport:
108108
private def parseMember(s: Tree): Option[Member] = processTreeOpt(s)(s match
109109
case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isSyntheticFunc && dd.symbol.isExtensionMethod =>
110110
dd.symbol.extendedSymbol.map { extSym =>
111-
val target = ExtensionTarget(extSym.symbol.name, extSym.tpt.dokkaType.asSignature, extSym.tpt.symbol.dri)
111+
val target = ExtensionTarget(
112+
extSym.symbol.normalizedName,
113+
extSym.tpt.dokkaType.asSignature,
114+
extSym.tpt.symbol.dri,
115+
extSym.symbol.pos.start
116+
)
112117
parseMethod(dd.symbol, kind = Kind.Extension(target))
113118
}
114119
// TODO check given methods?
@@ -163,7 +168,7 @@ trait ClassLikeSupport:
163168
private def parseInheritedMember(s: Tree): Option[Member] = processTreeOpt(s)(s match
164169
case c: ClassDef if c.symbol.shouldDocumentClasslike && !c.symbol.isGiven => Some(parseClasslike(c, signatureOnly = true))
165170
case other => parseMember(other)
166-
).map(_.withOrigin(Origin.InheritedFrom(s.symbol.owner.name, s.symbol.owner.dri)))
171+
).map(_.withOrigin(Origin.InheritedFrom(s.symbol.owner.normalizedName, s.symbol.owner.dri)))
167172

168173
extension (c: ClassDef):
169174
def membersToDocument = c.body.filterNot(_.symbol.isHiddenByVisibility)
@@ -196,7 +201,7 @@ trait ClassLikeSupport:
196201
}.toList
197202

198203
def getParameterModifier(parameter: Symbol): String =
199-
val fieldSymbol = c.symbol.field(parameter.name)
204+
val fieldSymbol = c.symbol.field(parameter.normalizedName)
200205
if fieldSymbol.flags.is(Flags.Mutable) then "var "
201206
else if fieldSymbol.flags.is(Flags.ParamAccessor) && !c.symbol.flags.is(Flags.Case) && !fieldSymbol.flags.is(Flags.Private) then "val "
202207
else ""
@@ -220,7 +225,6 @@ trait ClassLikeSupport:
220225

221226
def parseObject(classDef: ClassDef, signatureOnly: Boolean = false): DClass =
222227
DClass(classDef)(
223-
name = classDef.name.stripSuffix("$"),
224228
// All objects are final so we do not need final modifer!
225229
modifiers = classDef.symbol.getExtraModifiers().filter(_ != Modifier.Final),
226230
signatureOnly = signatureOnly
@@ -265,11 +269,7 @@ trait ClassLikeSupport:
265269
Kind.Implicit(Kind.Def, None)
266270
else kind
267271

268-
val name = methodKind match
269-
case Kind.Constructor => "this"
270-
case Kind.Given(_, _) => methodSymbol.name.stripPrefix("given_")
271-
case Kind.Extension(_) => methodSymbol.name.stripPrefix("extension_")
272-
case _ => methodSymbol.name
272+
val name = method.symbol.normalizedName
273273

274274
new DFunction(
275275
methodSymbol.dri,
@@ -301,7 +301,7 @@ trait ClassLikeSupport:
301301
def parseArgument(argument: ValDef, prefix: Symbol => String, isExtendedSymbol: Boolean = false, isGrouped: Boolean = false): DParameter =
302302
new DParameter(
303303
argument.symbol.dri,
304-
prefix(argument.symbol) + argument.symbol.name,
304+
prefix(argument.symbol) + argument.symbol.normalizedName,
305305
argument.symbol.documentation.asJava,
306306
null,
307307
argument.tpt.dokkaType,
@@ -319,7 +319,7 @@ trait ClassLikeSupport:
319319
else ""
320320

321321
new DTypeParameter(
322-
Invariance(TypeParameter(argument.symbol.dri, variancePrefix + argument.symbol.name, null)),
322+
Invariance(TypeParameter(argument.symbol.dri, variancePrefix + argument.symbol.normalizedName, null)),
323323
argument.symbol.documentation.asJava,
324324
null,
325325
JList(argument.rhs.dokkaType),
@@ -342,7 +342,7 @@ trait ClassLikeSupport:
342342

343343
new DProperty(
344344
typeDef.symbol.dri,
345-
typeDef.name,
345+
typeDef.symbol.normalizedName,
346346
/*documentation =*/ typeDef.symbol.documentation.asJava,
347347
/*expectPresentInSet =*/ null, // unused
348348
/*sources =*/ JMap(),
@@ -373,7 +373,7 @@ trait ClassLikeSupport:
373373

374374
new DProperty(
375375
valDef.symbol.dri,
376-
valDef.name,
376+
valDef.symbol.normalizedName,
377377
/*documentation =*/ valDef.symbol.documentation.asJava,
378378
/*expectPresentInSet =*/ null, // unused
379379
/*sources =*/ JMap(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package dotty.dokka.tasty
2+
3+
import dotty.dokka._
4+
5+
trait NameNormalizer { self: TastyParser =>
6+
import qctx.reflect._
7+
extension (s: Symbol) def normalizedName: String = {
8+
val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name
9+
val withoutObjectSuffix = if s.flags.is(Flags.Object) then withoutGivenPrefix.stripSuffix("$") else withoutGivenPrefix
10+
val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix
11+
constructorNormalizedName
12+
}
13+
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ trait DokkaBaseTastyInspector:
168168

169169
/** Parses a single Tasty compilation unit. */
170170
case class TastyParser(qctx: QuoteContext, inspector: DokkaBaseTastyInspector, config: DottyDokkaConfig)
171-
extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport:
171+
extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer:
172172
import qctx.reflect._
173173

174174
def sourceSet = inspector.sourceSet
@@ -179,7 +179,7 @@ case class TastyParser(qctx: QuoteContext, inspector: DokkaBaseTastyInspector, c
179179

180180
private def errorMsg[T](a: Any, m: => String, e: Throwable): Option[T] =
181181
val msg = try m catch case e: Throwable => a.toString
182-
println(s"ERROR: tree is faling: msg")
182+
println(s"ERROR: tree is faling: $msg")
183183
e.printStackTrace()
184184
throw e
185185

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ trait TypesSupport:
6161

6262
private def link(symbol: Symbol): List[JProjection] = {
6363
val suffix = if symbol.isValDef then texts(".type") else Nil
64-
(new TypeParameter(symbol.dri, symbol.name, null)) :: suffix
64+
(new TypeParameter(symbol.dri, symbol.normalizedName, null)) :: suffix
6565
}
6666

6767
private def commas(lists: List[List[JProjection]]) = lists match

scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala

+15-8
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,25 @@ import dotty.dokka.model.api._
1313
class ImplicitMembersExtensionTransformer(ctx: DokkaContext) extends DocumentableTransformer:
1414
override def invoke(original: DModule, context: DokkaContext): DModule =
1515
val classlikeMap = original.driMap
16+
val logger = context.getLogger
17+
18+
def retrieveCompanion(m: Member) = m match {
19+
case classlike: DClass =>
20+
val comp = ClasslikeExtension.getFrom(classlike).flatMap(_.companion)
21+
comp.flatMap { dri =>
22+
val res = classlikeMap.get(dri)
23+
if res.isEmpty then logger.warn(s"Companion for class ${classlike.name} exists but is missing in classlike map")
24+
res
25+
}
26+
case _ => None
27+
}
1628

1729
def expandMember(outerMembers: Seq[Member])(c: Member): Member =
18-
val companion = c match
19-
case classlike: DClass => ClasslikeExtension.getFrom(classlike).flatMap(_.companion).flatMap(classlikeMap.get)
20-
case _ => None
30+
val companion = retrieveCompanion(c)
2131

2232
val allParents = c.parents.flatMap(p => classlikeMap.get(p.dri))
2333

24-
val parentCompanions = allParents.flatMap {
25-
case cls: DClasslike => ClasslikeExtension.getFrom(cls).flatMap(_.companion).flatMap(classlikeMap.get)
26-
case _ => None
27-
}
34+
val parentCompanions = allParents.flatMap(retrieveCompanion)
2835

2936
// TODO (#220): We can expand this on generic etc
3037
val implictSources = outerMembers ++ companion.toSeq ++ parentCompanions
@@ -33,7 +40,7 @@ class ImplicitMembersExtensionTransformer(ctx: DokkaContext) extends Documentabl
3340

3441
val MyDri = c.getDri
3542
def collectApplicableMembers(source: Member): Seq[Member] = source.allMembers.flatMap {
36-
case m @ Member(_, _, _, Kind.Extension(ExtensionTarget(_, _, MyDri)), Origin.DefinedWithin) =>
43+
case m @ Member(_, _, _, Kind.Extension(ExtensionTarget(_, _, MyDri, _)), Origin.DefinedWithin) =>
3744
Seq(m.withOrigin(Origin.ExtensionFrom(source.name, source.dri)).withKind(Kind.Def))
3845
case m @ Member(_, _, _, conversionProvider: ImplicitConversionProvider, Origin.DefinedWithin) =>
3946
conversionProvider.conversion match

scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala

+8
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,14 @@ class ScalaPageContentBuilder(
247247

248248
def signature(d: Documentable) = addChildren(signatureProvider.signature(d).asScala.toList)
249249

250+
private def buildSignature(d: Documentable, s: Signature) = signatureProvider.asInstanceOf[ScalaSignatureProvider].signature(d, s)
251+
252+
def signature(d: Documentable, s: Signature) = addChild(buildSignature(d, s))
253+
254+
def inlineSignature(d: Documentable, s: Signature) = addChildren(
255+
buildSignature(d, s).getChildren.asScala.toSeq
256+
)
257+
250258
def defaultHeaders = List(
251259
contentForDRIs(
252260
dris = mainDRI,

scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala

+10-2
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,20 @@ class ScalaPageCreator(
315315
case _ => withNamedTags
316316
}
317317

318+
val withExtensionInformation = d.kind match {
319+
case Kind.Extension(on) =>
320+
val sourceSets = d.getSourceSets.asScala.toSet
321+
withCompanion.cell(sourceSets = sourceSets)(_.text("Extension"))
322+
.cell(sourceSets = sourceSets)(_.text(s"This function is an extension on (${on.name}: ").inlineSignature(d, on.signature).text(")"))
323+
case _ => withCompanion
324+
}
325+
318326
d match
319-
case null => withCompanion
327+
case null => withExtensionInformation
320328
case m: Member =>
321329
sourceLinks.pathTo(m).fold(withCompanion){ link =>
322330
val sourceSets = m.getSourceSets.asScala.toSet
323-
withCompanion.cell(sourceSets = sourceSets)(_.text("Source"))
331+
withExtensionInformation.cell(sourceSets = sourceSets)(_.text("Source"))
324332
.cell(sourceSets = sourceSets)(_.resolvedLink("(source)", link))
325333
}
326334
}

scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ class ScalaSignatureProvider(contentConverter: CommentsToContentConverter, logge
3030
def driLink(text: String, dri: DRI): SignatureBuilder = ContentNodeBuilder(builder.driLink(text, dri))
3131
}
3232

33-
override def signature(documentable: Documentable) =
33+
def signature(d: Member, s: Signature) = signatureContent(d){ builder =>
34+
val res = ContentNodeBuilder(builder).signature(s)
35+
res.asInstanceOf[ContentNodeBuilder].builder
36+
}
37+
38+
override def signature(documentable: Member) =
3439
JList(signatureContent(documentable){ builder =>
3540
val withAnnotations = ContentNodeBuilder(builder).annotationsBlock(documentable)
3641
val res = ScalaSignatureProvider.rawSignature(documentable, withAnnotations)

0 commit comments

Comments
 (0)