Skip to content

Commit

Permalink
Better support for exports
Browse files Browse the repository at this point in the history
  • Loading branch information
pikinier20 committed Dec 17, 2021
1 parent 2ab53f1 commit 6218178
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 52 deletions.
23 changes: 0 additions & 23 deletions scaladoc-testcases/src/tests/exports.scala

This file was deleted.

44 changes: 44 additions & 0 deletions scaladoc-testcases/src/tests/exports1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tests
package exports1

class A: //unexpected
def aDefInt: Int
= 1
def aDef1: 1
= 1
val aValInt: Int
= 1
val aVal1: 1
= 1
var aVarInt: Int
= 1
var aVar1: 1
= 1
type HKT[T[_], X] //expected: final type HKT = [T[_], X] =>> HKT[T, X]
= T[X]
def x[T[_], X](x: X): HKT[T, X]
= ???
def fn[T, U]: T => U
= ???
object Object //expected: val Obj: Object.type
val x: HKT[List, Int]
= ???
class Class(val a: Int, val b: Int) extends Serializable //expected: final type Class = Class
enum Enum: //expected: final type Enum = Enum
case A
case B(i: Int)
case C[T]() extends Enum

object X: //unexpected
def xDefInt: Int
= 1
def xDef1: 1
= 1
val xValInt: Int
= 1
val xVal1: 1
= 1
var xVarInt: Int
= 1
var xVar1: 1
= 1
12 changes: 12 additions & 0 deletions scaladoc-testcases/src/tests/exports2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package tests
package exports2

import exports1._

class B:
val a: A
= new A
export a.{Object => Obj, _}
export X._
def obj: Obj.type
= Obj
8 changes: 6 additions & 2 deletions scaladoc/src/dotty/tools/scaladoc/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ enum Kind(val name: String):
case Constructor(base: Kind.Def) extends Kind("def")
case Var extends Kind("var")
case Val extends Kind("val")
case Exported(m: Kind.Def) extends Kind("export")
case Exported(base: Kind) extends Kind("export")
case Type(concreate: Boolean, opaque: Boolean, typeParams: Seq[TypeParameter])
extends Kind("type") // should we handle opaque as modifier?
case Given(kind: Def | Class | Val.type, as: Option[Signature], conversion: Option[ImplicitConversion])
Expand All @@ -76,7 +76,7 @@ enum Kind(val name: String):
enum Origin:
case ImplicitlyAddedBy(name: String, dri: DRI)
case ExtensionFrom(name: String, dri: DRI)
case ExportedFrom(name: String, dri: Option[DRI])
case ExportedFrom(link: Option[Link])
case Overrides(overriddenMembers: Seq[Overridden])
case RegularlyDefined

Expand Down Expand Up @@ -186,8 +186,12 @@ extension[T] (member: Member)
def asLink: LinkToType = LinkToType(member.signature, member.dri, member.kind)
def membersBy(op: Member => Boolean): Seq[Member] = member.members.filter(op)

def withDRI(dri: DRI): Member = member.copy(dri = dri)

def withMembers(newMembers: Seq[Member]): Member = member.copy(members = newMembers)

def withName(name: String): Member = member.copy(name = name)

def updateRecusivly(op: Member => Member): Member =
val newMembers = member.members.map(_.updateRecusivly(op))
op(member).withMembers(newMembers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,9 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext
Seq("Implicitly added by ", renderLink(name, dri))
case Origin.ExtensionFrom(name, dri) =>
Seq("Extension method from ", renderLink(name, dri))
case Origin.ExportedFrom(name, dri) =>
val signatureName: TagArg = dri match
case Some(dri: DRI) => renderLink(name, dri)
case None => name
case Origin.ExportedFrom(Some(link)) =>
val signatureName: TagArg = link match
case Link(name, dri) => renderLink(name, dri)
Seq("Exported from ", signatureName)
case _ => Nil
}
Expand All @@ -132,7 +131,7 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext
val depStyle = if member.deprecated.isEmpty then "" else "deprecated"
val nameClasses = cls := s"documentableName $depStyle"

val rawBuilder = ScalaSignatureProvider.rawSignature(member, InlineSignatureBuilder())
val rawBuilder = ScalaSignatureProvider.rawSignature(member, InlineSignatureBuilder())()
val inlineBuilder = rawBuilder.asInstanceOf[InlineSignatureBuilder]
val kind :: modifiersRevered = inlineBuilder.preName
val signature = inlineBuilder.names.reverse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ trait Resources(using ctx: DocContext) extends Locations, Writer:
case m: Member if m.kind != Kind.RootPackage =>
val descr = m.dri.asFileLocation
def processMember(member: Member): Seq[JSON] =
val signatureBuilder = ScalaSignatureProvider.rawSignature(member, InlineSignatureBuilder()).asInstanceOf[InlineSignatureBuilder]
val signatureBuilder = ScalaSignatureProvider.rawSignature(member, InlineSignatureBuilder())().asInstanceOf[InlineSignatureBuilder]
val sig = Signature(Plain(s"${member.kind.name} "), Plain(member.name)) ++ signatureBuilder.names.reverse
val entry = mkEntry(member.dri, member.name, flattenToText(sig), descr, member.kind.name)
val children = member
Expand Down
35 changes: 20 additions & 15 deletions scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -149,21 +149,23 @@ trait ClassLikeSupport:
}

case dd: DefDef if !dd.symbol.isHiddenByVisibility && dd.symbol.isExported && !dd.symbol.isArtifact =>
val exportedTarget = dd.rhs.collect {
case a: Apply => a.fun.asInstanceOf[Select]
case s: Select => s
dd.rhs.map {
case TypeApply(rhs, _) => rhs
case Apply(TypeApply(rhs, _), _) => rhs
case rhs => rhs
}.map(_.tpe.termSymbol).filter(_.exists).map(_.tree).map {
case v: ValDef if v.symbol.flags.is(Flags.Module) && !v.symbol.flags.is(Flags.Synthetic) =>
v.symbol.owner -> Symbol.newVal(c.symbol, dd.name, v.tpt.tpe, Flags.Final, Symbol.noSymbol).tree
case other => other.symbol.owner -> other
}.flatMap { (originalOwner, tree) =>
parseMember(c)(tree)
.map { m => m
.withDRI(dd.symbol.dri)
.withName(dd.symbol.normalizedName)
.withKind(Kind.Exported(m.kind))
.withOrigin(Origin.ExportedFrom(Some(Link(originalOwner.normalizedName, originalOwner.dri))))
}
}
val functionName = exportedTarget.fold("function")(_.name)
val instanceName = exportedTarget.collect {
case Select(qualifier: Select, _) => qualifier.name
case Select(qualifier: Ident, _) => qualifier.tpe.typeSymbol.normalizedName
}.getOrElse("instance")
val dri = dd.rhs.collect {
case s: Select if s.symbol.isDefDef => s.symbol.dri
}.orElse(exportedTarget.map(_.qualifier.tpe.typeSymbol.dri))

Some(parseMethod(c, dd.symbol, specificKind = Kind.Exported(_))
.withOrigin(Origin.ExportedFrom(s"$instanceName.$functionName", dri)))

case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isSyntheticFunc && !dd.symbol.isExtensionMethod && !dd.symbol.isArtifact =>
Some(parseMethod(c, dd.symbol))
Expand Down Expand Up @@ -423,7 +425,10 @@ trait ClassLikeSupport:
val defaultKind = Kind.Type(!isTreeAbstract(typeDef.rhs), typeDef.symbol.isOpaque, generics).asInstanceOf[Kind.Type]
val kind = if typeDef.symbol.flags.is(Flags.Enum) then Kind.EnumCase(defaultKind)
else defaultKind
mkMember(typeDef.symbol, kind, tpeTree.asSignature)(deprecated = typeDef.symbol.isDeprecated())

if typeDef.symbol.flags.is(Flags.Exported)
then mkMember(typeDef.symbol, Kind.Exported(kind), tpeTree.asSignature)(deprecated = typeDef.symbol.isDeprecated(), origin = Origin.ExportedFrom(None))
else mkMember(typeDef.symbol, kind, tpeTree.asSignature)(deprecated = typeDef.symbol.isDeprecated())

def parseValDef(c: ClassDef, valDef: ValDef): Member =
def defaultKind = if valDef.symbol.flags.is(Flags.Mutable) then Kind.Var else Kind.Val
Expand Down
3 changes: 2 additions & 1 deletion scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ trait TypesSupport:
private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: reflect.TypeRepr, high: reflect.TypeRepr) =
import reflect._
def regularTypeBounds(low: TypeRepr, high: TypeRepr) =
typeBound(low, low = true) ++ typeBound(high, low = false)
if low == high then keyword(" = ").l ++ inner(low)
else typeBound(low, low = true) ++ typeBound(high, low = false)
high.match
case TypeLambda(params, paramBounds, resType) =>
if resType.typeSymbol == defn.AnyClass then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object FilterAttributes:
private def origin(m: Member): Map[String, String] = m.origin match
case Origin.ImplicitlyAddedBy(name, _) => Map("implicitly" -> s"by $name")
case Origin.ExtensionFrom(name, _) => Map("extension" -> s"from $name")
case Origin.ExportedFrom(name, _) => Map("export" -> s"from $name")
case Origin.ExportedFrom(Some(link)) => Map("export" -> s"from ${link.name}}")
case _ => Map.empty


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ package dotty.tools.scaladoc
package translators

object ScalaSignatureProvider:
def rawSignature(documentable: Member, builder: SignatureBuilder): SignatureBuilder =
documentable.kind match
def rawSignature(documentable: Member, builder: SignatureBuilder)(kind: Kind = documentable.kind): SignatureBuilder =
kind match
case Kind.Extension(_, m) =>
extensionSignature(documentable, m, builder)
case Kind.Exported(d) =>
methodSignature(documentable, d, builder)
rawSignature(documentable, builder)(d)
case d: Kind.Def =>
methodSignature(documentable, d, builder)
case Kind.Constructor(d) =>
Expand All @@ -33,7 +33,7 @@ object ScalaSignatureProvider:
case trt: Kind.Trait =>
traitSignature(documentable, trt, builder)
case Kind.Val | Kind.Var | Kind.Implicit(Kind.Val, _) =>
fieldSignature(documentable, documentable.kind.name, builder)
fieldSignature(documentable, kind.name, builder)
case tpe: Kind.Type =>
typeSignature(tpe, documentable, builder)
case Kind.Package =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ class SpecializedSignature extends SignatureTest("specializedSignature", Signatu
class ContextBounds extends SignatureTest("contextBounds", SignatureTest.all)

class FBoundedTypeParameters extends SignatureTest("fboundedTypeParameters", SignatureTest.all)

class Exports extends SignatureTest("exports2", SignatureTest.all, sourceFiles = List("exports1", "exports2"))

0 comments on commit 6218178

Please sign in to comment.