-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Scala3doc: Add missing givens, create pages for givens, minor bugfixes #10306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,7 +57,7 @@ trait ClassLikeSupport: | |
|
||
val graph = HierarchyGraph.withEdges(getSupertypesGraph(classDef, LinkToType(selfSiangture, classDef.symbol.dri, kindForClasslike(classDef.symbol)))) | ||
val baseExtra = PropertyContainer.Companion.empty() | ||
.plus(ClasslikeExtension(classDef.getConstructorMethod, classDef.getCompanion)) | ||
.plus(ClasslikeExtension(classDef.getConstructorMethod(), classDef.getCompanion)) | ||
.plus(MemberExtension( | ||
classDef.symbol.getVisibility(), | ||
modifiers, | ||
|
@@ -111,25 +111,55 @@ trait ClassLikeSupport: | |
val target = ExtensionTarget(extSym.symbol.name, extSym.tpt.dokkaType.asSignature, extSym.tpt.symbol.dri) | ||
parseMethod(dd.symbol, kind = Kind.Extension(target)) | ||
} | ||
|
||
// TODO check given methods? | ||
case dd: DefDef if !dd.symbol.isHiddenByVisibility && dd.symbol.isGiven => | ||
Some(parseMethod(dd.symbol, kind = Kind.Given(getGivenInstance(dd).map(_.asSignature), None))) // TODO check given methods? | ||
Some(dd.symbol.owner.typeMember(dd.name)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can
|
||
.filterNot(_.exists) | ||
.map { _ => | ||
parseMethod(dd.symbol, kind = Kind.Given(getGivenInstance(dd).map(_.asSignature), None)) | ||
} | ||
|
||
case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isGiven && !dd.symbol.isSyntheticFunc && !dd.symbol.isExtensionMethod => | ||
Some(parseMethod(dd.symbol)) | ||
|
||
case td: TypeDef if !td.symbol.flags.is(Flags.Synthetic) && (!td.symbol.flags.is(Flags.Case) || !td.symbol.flags.is(Flags.Enum)) => | ||
Some(parseTypeDef(td)) | ||
|
||
case vd: ValDef if !isSyntheticField(vd.symbol) | ||
&& (!vd.symbol.flags.is(Flags.Case) || !vd.symbol.flags.is(Flags.Enum)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we can exctract all this conditions to dedicated method? |
||
&& vd.symbol.isGiven => | ||
val classDef = Some(vd.tpt.tpe).flatMap(_.classSymbol.map(_.tree.asInstanceOf[ClassDef])) | ||
Some(classDef.filter(_.symbol.flags.is(Flags.ModuleClass)).fold[Member](parseValDef(vd))(parseGivenClasslike(_))) | ||
|
||
case vd: ValDef if !isSyntheticField(vd.symbol) && (!vd.symbol.flags.is(Flags.Case) || !vd.symbol.flags.is(Flags.Enum)) => | ||
Some(parseValDef(vd)) | ||
|
||
case c: ClassDef if c.symbol.owner.method(c.name).exists(_.flags.is(Flags.Given)) => | ||
Some(parseGivenClasslike(c)) | ||
|
||
case c: ClassDef if c.symbol.shouldDocumentClasslike && !c.symbol.isGiven => | ||
Some(parseClasslike(c)) | ||
|
||
case _ => None | ||
) | ||
|
||
private def parseGivenClasslike(c: ClassDef): Member = { | ||
val parsedClasslike = parseClasslike(c) | ||
val parentTpe = c.parents(0) match { | ||
case t: TypeTree => Some(t.tpe) | ||
case _ => None | ||
} | ||
val modifiedClasslikeExtension = ClasslikeExtension.getFrom(parsedClasslike).map(_.copy( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you first call |
||
constructor = c.getConstructorMethod(Some(_ => "using ")) | ||
) | ||
).get | ||
parsedClasslike.withNewExtras( | ||
parsedClasslike.getExtra.plus(modifiedClasslikeExtension) | ||
).withKind( | ||
Kind.Given(parsedClasslike.directParents.headOption, parentTpe.flatMap(extractImplicitConversion)) | ||
) | ||
} | ||
|
||
private def parseInheritedMember(s: Tree): Option[Member] = processTreeOpt(s)(s match | ||
case c: ClassDef if c.symbol.shouldDocumentClasslike && !c.symbol.isGiven => Some(parseClasslike(c, signatureOnly = true)) | ||
case other => parseMember(other) | ||
|
@@ -178,9 +208,9 @@ trait ClassLikeSupport: | |
.filterNot(_.isHiddenByVisibility) | ||
.map(_.dri) | ||
|
||
def getConstructorMethod: Option[DFunction] = | ||
def getConstructorMethod(paramModifierFunc: Option[Symbol => String] = None): Option[DFunction] = | ||
Some(c.constructor.symbol).filter(_.exists).filterNot(_.isHiddenByVisibility).map( d => | ||
parseMethod(d, constructorWithoutParamLists(c), s => c.getParameterModifier(s)) | ||
parseMethod(d, constructorWithoutParamLists(c), paramModifierFunc.getOrElse(s => c.getParameterModifier(s))) | ||
) | ||
|
||
def parseClasslike(classDef: ClassDef, signatureOnly: Boolean = false)(using ctx: Context): DClass = classDef match | ||
|
@@ -238,6 +268,7 @@ trait ClassLikeSupport: | |
val name = methodKind match | ||
case Kind.Constructor => "this" | ||
case Kind.Given(_, _) => methodSymbol.name.stripPrefix("given_") | ||
case Kind.Extension(_) => methodSymbol.name.stripPrefix("extension_") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should no longer be necessary, the encoding of extension methods has changed and their names AFAIU are no longer prefixed with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the version of |
||
case _ => methodSymbol.name | ||
|
||
new DFunction( | ||
|
@@ -333,18 +364,10 @@ trait ClassLikeSupport: | |
) | ||
|
||
def parseValDef(valDef: ValDef): DProperty = | ||
def givenInstance = Some(valDef.symbol.moduleClass) | ||
.filter(_.exists) | ||
.map(_.tree.asInstanceOf[ClassDef]) | ||
.flatMap(_.getParents.headOption) | ||
.map(_.dokkaType.asSignature) | ||
|
||
def defaultKind = if valDef.symbol.flags.is(Flags.Mutable) then Kind.Var else Kind.Val | ||
val kind = | ||
if valDef.symbol.isGiven then Kind.Given(givenInstance, extractImplicitConversion(valDef.tpt.tpe)) | ||
else if valDef.symbol.flags.is(Flags.Implicit) then | ||
val kind = if valDef.symbol.flags.is(Flags.Implicit) then | ||
Kind.Implicit(Kind.Val, extractImplicitConversion(valDef.tpt.tpe)) | ||
else defaultKind | ||
else defaultKind | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the indent? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without indent there, I've got:
|
||
|
||
new DProperty( | ||
valDef.symbol.dri, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,13 +17,13 @@ class ImplicitMembersExtensionTransformer(ctx: DokkaContext) extends Documentabl | |
|
||
def expandMember(outerMembers: Seq[Member])(c: Member): Member = | ||
val companion = c match | ||
case classlike: DClass => ClasslikeExtension.getFrom(classlike).flatMap(_.companion).map(classlikeMap) | ||
case classlike: DClass => ClasslikeExtension.getFrom(classlike).flatMap(_.companion).flatMap(classlikeMap.get) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it expected that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ahh, actually I changed it on the beginning of implementing this PR because it was throwing exceptions, but I've checked and this change is unnecessary |
||
case _ => None | ||
|
||
val allParents = c.parents.flatMap(p => classlikeMap.get(p.dri)) | ||
|
||
val parentCompanions = allParents.flatMap { | ||
case cls: DClasslike => ClasslikeExtension.getFrom(cls).flatMap(_.companion).map(classlikeMap) | ||
case cls: DClasslike => ClasslikeExtension.getFrom(cls).flatMap(_.companion).flatMap(classlikeMap.get) | ||
case _ => None | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,8 @@ object ScalaSignatureProvider: | |
methodSignature(method, builder) | ||
case enumEntry: DClass if enumEntry.kind == Kind.EnumCase => | ||
enumEntrySignature(enumEntry, builder) | ||
case givenClazz: DClass if givenClazz.kind.isInstanceOf[Kind.Given] => | ||
givenClassSignature(givenClazz, builder) | ||
case clazz: DClass => | ||
classSignature(clazz, builder) | ||
case enumProperty: DProperty if enumProperty.kind == Kind.EnumCase => | ||
|
@@ -98,6 +100,22 @@ object ScalaSignatureProvider: | |
val extendPart = builder.text(" extends ").signature(extendType) | ||
withTypes.foldLeft(extendPart)((bdr, tpe) => bdr.text(" with ").signature(tpe)) | ||
|
||
private def givenClassSignature(clazz: DClass, builder: SignatureBuilder): SignatureBuilder = | ||
val ext = clazz.get(ClasslikeExtension) | ||
val prefixes = builder | ||
.modifiersAndVisibility(clazz, "given") | ||
.name(clazz.getName, clazz.getDri) | ||
.generics(clazz) | ||
|
||
val withGenerics = ext.constructor.toSeq.foldLeft(prefixes){ (bdr, elem) => | ||
bdr.functionParameters(elem) | ||
} | ||
clazz.kind match | ||
case Kind.Given(Some(instance), _) => withGenerics | ||
.text(" as ") | ||
.signature(instance) | ||
case _ => withGenerics | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we have tests for this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's actually tested by |
||
|
||
private def classSignature(clazz: DClass, builder: SignatureBuilder): SignatureBuilder = | ||
val ext = clazz.get(ClasslikeExtension) | ||
val prefixes = builder | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can check given methods as part of this PR?