From 6cd9d91e9f7ffb5d74b93ee43255667970e39816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Zyba=C5=82a?= Date: Fri, 13 Nov 2020 10:37:01 +0100 Subject: [PATCH] Add missing givens, create pages for givens, minor bugfixes --- .../dotty/dokka/tasty/ClassLikeSupport.scala | 53 +++++++++++++------ .../dotty/dokka/tasty/SyntheticSupport.scala | 4 +- .../ImplicitMembersExtensionTransformer.scala | 4 +- .../translators/ScalaSignatureProvider.scala | 18 +++++++ 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala index 87d0a8297248..73a32fe04e09 100644 --- a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala @@ -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,9 +111,13 @@ 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)) + .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)) @@ -121,15 +125,41 @@ trait ClassLikeSupport: 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)) + && 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( + 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_") 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 new DProperty( valDef.symbol.dri, diff --git a/scala3doc/src/dotty/dokka/tasty/SyntheticSupport.scala b/scala3doc/src/dotty/dokka/tasty/SyntheticSupport.scala index d8d4078856f2..3b97d08220ba 100644 --- a/scala3doc/src/dotty/dokka/tasty/SyntheticSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/SyntheticSupport.scala @@ -38,7 +38,7 @@ trait SyntheticsSupport: def getAllMembers: List[Symbol] = hackGetAllMembers(qctx.reflect)(s) def isSyntheticField(c: Symbol) = - c.flags.is(Flags.CaseAccessor) || c.flags.is(Flags.Object) + c.flags.is(Flags.CaseAccessor) || (c.flags.is(Flags.Object) && !c.flags.is(Flags.Given)) def isValidPos(pos: Position) = pos.exists && pos.start != pos.end @@ -69,7 +69,7 @@ trait SyntheticsSupport: sym.typeRef.appliedTo(sym.typeParams.map(_.typeRef)).allMembers.iterator.map(_.symbol) .collect { case sym if - !sym.is(dotc.core.Flags.ModuleVal) && + (!sym.is(dotc.core.Flags.ModuleVal) || sym.is(dotc.core.Flags.Given)) && !sym.flags.isAllOf(dotc.core.Flags.Enum | dotc.core.Flags.Case | dotc.core.Flags.JavaStatic) => sym.asInstanceOf[r.Symbol] }.toList diff --git a/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala b/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala index 0100dd041ee0..cac96da63409 100644 --- a/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala +++ b/scala3doc/src/dotty/dokka/transformers/ImplicitMembersExtensionTransformer.scala @@ -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) 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 } diff --git a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala index efede2229fbf..35911cbd1e18 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala @@ -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 + private def classSignature(clazz: DClass, builder: SignatureBuilder): SignatureBuilder = val ext = clazz.get(ClasslikeExtension) val prefixes = builder