@@ -27,7 +27,7 @@ trait ClassLikeSupport:
2727 else Kind .Class (Nil , Nil )
2828
2929 private def kindForClasslike (classDef : ClassDef ): Kind =
30- def typeArgs = classDef.getTypeParams.map(mkTypeArgument)
30+ def typeArgs = classDef.getTypeParams.map(mkTypeArgument(_) )
3131
3232 def parameterModifier (parameter : Symbol ): String =
3333 val fieldSymbol = classDef.symbol.declaredField(parameter.normalizedName)
@@ -125,7 +125,7 @@ trait ClassLikeSupport:
125125 private def isDocumentableExtension (s : Symbol ) =
126126 ! s.isHiddenByVisibility && ! s.isSyntheticFunc && s.isExtensionMethod
127127
128- private def parseMember (s : Tree ): Option [Member ] = processTreeOpt(s)(s match
128+ private def parseMember (c : ClassDef )( s : Tree ): Option [Member ] = processTreeOpt(s)(s match
129129 case dd : DefDef if isDocumentableExtension(dd.symbol) =>
130130 dd.symbol.extendedSymbol.map { extSym =>
131131 val target = ExtensionTarget (
@@ -134,14 +134,14 @@ trait ClassLikeSupport:
134134 extSym.tpt.symbol.dri,
135135 extSym.symbol.pos.get.start
136136 )
137- parseMethod(dd.symbol,specificKind = Kind .Extension (target, _))
137+ parseMethod(c, dd.symbol,specificKind = Kind .Extension (target, _))
138138 }
139139 // TODO check given methods?
140140 case dd : DefDef if ! dd.symbol.isHiddenByVisibility && dd.symbol.isGiven =>
141141 Some (dd.symbol.owner.memberType(dd.name))
142142 .filterNot(_.exists)
143143 .map { _ =>
144- parseMethod(dd.symbol, specificKind =
144+ parseMethod(c, dd.symbol, specificKind =
145145 Kind .Given (_, getGivenInstance(dd).map(_.asSignature), None )
146146 )
147147 }
@@ -160,11 +160,11 @@ trait ClassLikeSupport:
160160 case s : Select if s.symbol.isDefDef => s.symbol.dri
161161 }.orElse(exportedTarget.map(_.qualifier.tpe.typeSymbol.dri))
162162
163- Some (parseMethod(dd.symbol, specificKind = Kind .Exported (_))
163+ Some (parseMethod(c, dd.symbol, specificKind = Kind .Exported (_))
164164 .withOrigin(Origin .ExportedFrom (s " $instanceName. $functionName" , dri)))
165165
166166 case dd : DefDef if ! dd.symbol.isHiddenByVisibility && ! dd.symbol.isGiven && ! dd.symbol.isSyntheticFunc && ! dd.symbol.isExtensionMethod =>
167- Some (parseMethod(dd.symbol))
167+ Some (parseMethod(c, dd.symbol))
168168
169169 case td : TypeDef if ! td.symbol.flags.is(Flags .Synthetic ) && (! td.symbol.flags.is(Flags .Case ) || ! td.symbol.flags.is(Flags .Enum )) =>
170170 Some (parseTypeDef(td))
@@ -173,10 +173,10 @@ trait ClassLikeSupport:
173173 && (! vd.symbol.flags.is(Flags .Case ) || ! vd.symbol.flags.is(Flags .Enum ))
174174 && vd.symbol.isGiven =>
175175 val classDef = Some (vd.tpt.tpe).flatMap(_.classSymbol.map(_.tree.asInstanceOf [ClassDef ]))
176- Some (classDef.filter(_.symbol.flags.is(Flags .Module )).fold[Member ](parseValDef(vd))(parseGivenClasslike(_)))
176+ Some (classDef.filter(_.symbol.flags.is(Flags .Module )).fold[Member ](parseValDef(c, vd))(parseGivenClasslike(_)))
177177
178178 case vd : ValDef if ! isSyntheticField(vd.symbol) && (! vd.symbol.flags.is(Flags .Case ) || ! vd.symbol.flags.is(Flags .Enum )) =>
179- Some (parseValDef(vd))
179+ Some (parseValDef(c, vd))
180180
181181 case c : ClassDef if c.symbol.owner.memberMethod(c.name).exists(_.flags.is(Flags .Given )) =>
182182 Some (parseGivenClasslike(c))
@@ -210,9 +210,9 @@ trait ClassLikeSupport:
210210 )
211211 }
212212
213- private def parseInheritedMember (s : Tree ): Option [Member ] = processTreeOpt(s)(s match
213+ private def parseInheritedMember (c : ClassDef )( s : Tree ): Option [Member ] = processTreeOpt(s)(s match
214214 case c : ClassDef if c.symbol.shouldDocumentClasslike && ! c.symbol.isGiven => Some (parseClasslike(c, signatureOnly = true ))
215- case other => parseMember(other)
215+ case other => parseMember(c)( other)
216216 ).map(_.withInheritedFrom(InheritedFrom (s.symbol.owner.normalizedName, s.symbol.owner.dri)))
217217
218218 extension (c : ClassDef )
@@ -228,8 +228,8 @@ trait ClassLikeSupport:
228228 case dd : DefDef if ! dd.symbol.isClassConstructor && ! (dd.symbol.isSuperBridgeMethod || dd.symbol.isDefaultHelperMethod) => dd
229229 case other => other
230230 }
231- c.membersToDocument.flatMap(parseMember) ++
232- inherited.flatMap(s => parseInheritedMember(s))
231+ c.membersToDocument.flatMap(parseMember(c) ) ++
232+ inherited.flatMap(s => parseInheritedMember(c)( s))
233233 }
234234
235235 /** Extracts members while taking Dotty logic for patching the stdlib into account. */
@@ -240,7 +240,7 @@ trait ClassLikeSupport:
240240 val ownMemberDRIs = ownMembers.iterator.map(_.name).toSet + " experimental$"
241241 sym.tree.asInstanceOf [ClassDef ]
242242 .membersToDocument.filterNot(m => ownMemberDRIs.contains(m.symbol.name))
243- .flatMap(parseMember)
243+ .flatMap(parseMember(c) )
244244 }
245245 c.symbol.fullName match {
246246 case " scala.Predef$" =>
@@ -302,7 +302,7 @@ trait ClassLikeSupport:
302302
303303 val enumVals = companion.membersToDocument.collect {
304304 case vd : ValDef if ! isSyntheticField(vd.symbol) && vd.symbol.flags.is(Flags .Enum ) && vd.symbol.flags.is(Flags .Case ) => vd
305- }.toList.map(parseValDef(_))
305+ }.toList.map(parseValDef(classDef, _))
306306
307307 val enumTypes = companion.membersToDocument.collect {
308308 case td : TypeDef if ! td.symbol.flags.is(Flags .Synthetic ) && td.symbol.flags.is(Flags .Enum ) && td.symbol.flags.is(Flags .Case ) => td
@@ -321,6 +321,7 @@ trait ClassLikeSupport:
321321 classlikie.withNewMembers(cases).asInstanceOf [DClass ]
322322
323323 def parseMethod (
324+ c : ClassDef ,
324325 methodSymbol : Symbol ,
325326 emptyParamsList : Boolean = false ,
326327 paramPrefix : Symbol => String = _ => " " ,
@@ -336,9 +337,13 @@ trait ClassLikeSupport:
336337 else method.paramss
337338 val genericTypes = if (methodSymbol.isClassConstructor) Nil else method.typeParams
338339
340+ val memberInfo = unwrapMemberInfo(c, methodSymbol)
341+
339342 val basicKind : Kind .Def = Kind .Def (
340- genericTypes.map(mkTypeArgument),
341- paramLists.map(pList => ParametersList (pList.map(mkParameter(_, paramPrefix)), if isUsingModifier(pList) then " using " else " " ))
343+ genericTypes.map(mkTypeArgument(_, memberInfo.genericTypes)),
344+ paramLists.zipWithIndex.map { (pList, index) =>
345+ ParametersList (pList.map(mkParameter(_, paramPrefix, memberInfo = memberInfo.paramLists(index))), if isUsingModifier(pList) then " using " else " " )
346+ }
342347 )
343348
344349 val methodKind =
@@ -368,7 +373,7 @@ trait ClassLikeSupport:
368373 methodSymbol.getExtraModifiers(),
369374 methodKind,
370375 methodSymbol.getAnnotations(),
371- method.returnTpt .dokkaType.asSignature,
376+ memberInfo.res .dokkaType.asSignature,
372377 methodSymbol.source(using qctx),
373378 origin
374379 )
@@ -377,32 +382,33 @@ trait ClassLikeSupport:
377382 def mkParameter (argument : ValDef ,
378383 prefix : Symbol => String = _ => " " ,
379384 isExtendedSymbol : Boolean = false ,
380- isGrouped : Boolean = false ) =
385+ isGrouped : Boolean = false ,
386+ memberInfo : Map [String , TypeRepr ] = Map .empty) =
381387 val inlinePrefix = if argument.symbol.flags.is(Flags .Inline ) then " inline " else " "
382- val name = Option .when(! argument.symbol.flags.is(Flags .Synthetic ))(argument.symbol.normalizedName)
383-
388+ val nameIfNotSynthetic = Option .when(! argument.symbol.flags.is(Flags .Synthetic ))(argument.symbol.normalizedName)
389+ val name = argument.symbol.normalizedName
384390 Parameter (
385391 argument.symbol.getAnnotations(),
386392 inlinePrefix + prefix(argument.symbol),
387- name ,
393+ nameIfNotSynthetic ,
388394 argument.symbol.dri,
389- argument.tpt.dokkaType.asSignature,
395+ memberInfo.get(name).fold( argument.tpt.dokkaType.asSignature)(_.dokkaType.asSignature) ,
390396 isExtendedSymbol,
391397 isGrouped
392398 )
393399
394- def mkTypeArgument (argument : TypeDef ): TypeParameter =
400+ def mkTypeArgument (argument : TypeDef , memberInfo : Map [ String , TypeBounds ] = Map .empty ): TypeParameter =
395401 val variancePrefix : " +" | " -" | " " =
396402 if argument.symbol.flags.is(Flags .Covariant ) then " +"
397403 else if argument.symbol.flags.is(Flags .Contravariant ) then " -"
398404 else " "
399-
405+ val name = argument.symbol.normalizedName
400406 TypeParameter (
401407 argument.symbol.getAnnotations(),
402408 variancePrefix,
403- argument.symbol.normalizedName ,
409+ name ,
404410 argument.symbol.dri,
405- argument.rhs.dokkaType.asSignature
411+ memberInfo.get(name).fold( argument.rhs.dokkaType.asSignature)(_.dokkaType.asSignature)
406412 )
407413
408414 def parseTypeDef (typeDef : TypeDef ): Member =
@@ -413,7 +419,7 @@ trait ClassLikeSupport:
413419 }
414420
415421 val (generics, tpeTree) = typeDef.rhs match
416- case LambdaTypeTree (params, body) => (params.map(mkTypeArgument), body)
422+ case LambdaTypeTree (params, body) => (params.map(mkTypeArgument(_) ), body)
417423 case tpe => (Nil , tpe)
418424
419425 mkMember(
@@ -428,8 +434,9 @@ trait ClassLikeSupport:
428434 )
429435 )
430436
431- def parseValDef (valDef : ValDef ): Member =
437+ def parseValDef (c : ClassDef , valDef : ValDef ): Member =
432438 def defaultKind = if valDef.symbol.flags.is(Flags .Mutable ) then Kind .Var else Kind .Val
439+ val memberInfo = unwrapMemberInfo(c, valDef.symbol)
433440 val kind = if valDef.symbol.flags.is(Flags .Implicit ) then
434441 Kind .Implicit (Kind .Val , extractImplicitConversion(valDef.tpt.tpe))
435442 else defaultKind
@@ -441,7 +448,7 @@ trait ClassLikeSupport:
441448 valDef.symbol.getExtraModifiers(),
442449 kind,
443450 valDef.symbol.getAnnotations(),
444- valDef.tpt.tpe .dokkaType.asSignature,
451+ memberInfo.res .dokkaType.asSignature,
445452 valDef.symbol.source(using qctx)
446453 )
447454 )
@@ -472,5 +479,27 @@ trait ClassLikeSupport:
472479 PropertyContainer .Companion .empty().plus(member.copy(rawDoc = symbol.documentation)).plus(compositeExt)
473480 )
474481
482+ case class MemberInfo (genericTypes : Map [String , TypeBounds ], paramLists : List [Map [String , TypeRepr ]], res : TypeRepr )
483+
484+ def unwrapMemberInfo (c : ClassDef , symbol : Symbol ): MemberInfo =
485+ val baseTypeRepr = memberInfo(c, symbol)
486+
487+ def handlePolyType (polyType : PolyType ): MemberInfo =
488+ MemberInfo (polyType.paramNames.zip(polyType.paramBounds).toMap, List .empty, polyType.resType)
489+
490+ def handleMethodType (memberInfo : MemberInfo , methodType : MethodType ): MemberInfo =
491+ MemberInfo (memberInfo.genericTypes, memberInfo.paramLists ++ List (methodType.paramNames.zip(methodType.paramTypes).toMap), methodType.resType)
492+
493+ def handleByNameType (memberInfo : MemberInfo , byNameType : ByNameType ): MemberInfo =
494+ MemberInfo (memberInfo.genericTypes, memberInfo.paramLists, byNameType.underlying)
495+
496+ def recursivelyCalculateMemberInfo (memberInfo : MemberInfo ): MemberInfo = memberInfo.res match
497+ case p : PolyType => recursivelyCalculateMemberInfo(handlePolyType(p))
498+ case m : MethodType => recursivelyCalculateMemberInfo(handleMethodType(memberInfo, m))
499+ case b : ByNameType => handleByNameType(memberInfo, b)
500+ case _ => memberInfo
501+
502+ recursivelyCalculateMemberInfo(MemberInfo (Map .empty, List .empty, baseTypeRepr))
503+
475504 private def isUsingModifier (parameters : Seq [ValDef ]): Boolean =
476505 parameters.size > 0 && parameters(0 ).symbol.flags.is(Flags .Given )
0 commit comments