Skip to content

Handle exports presenting in scala3doc #10504

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

Merged
merged 5 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2436,6 +2436,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
def EmptyFlags = dotc.core.Flags.EmptyFlags
def Enum: Flags = dotc.core.Flags.Enum
def Erased: Flags = dotc.core.Flags.Erased
def Exported: Flags = dotc.core.Flags.Exported
def ExtensionMethod: Flags = dotc.core.Flags.ExtensionMethod
def FieldAccessor: Flags = dotc.core.Flags.Accessor
def Final: Flags = dotc.core.Flags.Final
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ object SourceCode {
if (flags.is(Flags.Enum)) flagList += "enum"
if (flags.is(Flags.Erased)) flagList += "erased"
if (flags.is(Flags.ExtensionMethod)) flagList += "extension"
if (flags.is(Flags.Exported)) flagList += "exported"
if (flags.is(Flags.FieldAccessor)) flagList += "accessor"
if (flags.is(Flags.Final)) flagList += "final"
if (flags.is(Flags.HasDefault)) flagList += "hasDefault"
Expand Down
3 changes: 3 additions & 0 deletions library/src/scala/quoted/Quotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3154,6 +3154,9 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
/** Is this symbol `erased` */
def Erased: Flags

/** Is this symbol exported from provided instance */
def Exported: Flags

/** Is this symbol a `def` defined in an `extension` */
def ExtensionMethod: Flags

Expand Down
2 changes: 2 additions & 0 deletions scala3doc/src/dotty/dokka/model/api/api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enum Kind(val name: String){
case Constructor extends Kind("def")
case Var extends Kind("var")
case Val extends Kind("val")
case Exported extends Kind("export")
case Type(concreate: Boolean, opaque: Boolean) extends Kind("Type") // should we handle opaque as modifier?
case Given(as: Option[Signature], conversion: Option[ImplicitConversion]) extends Kind("Given") with ImplicitConversionProvider
case Implicit(kind: Kind, conversion: Option[ImplicitConversion]) extends Kind(kind.name) with ImplicitConversionProvider
Expand All @@ -73,6 +74,7 @@ enum Origin:
case InheritedFrom(name: String, dri: DRI)
case ImplicitlyAddedBy(name: String, dri: DRI)
case ExtensionFrom(name: String, dri: DRI)
case ExportedFrom(name: String, dri: DRI)
case DefinedWithin

case class Annotation(val dri: DRI, val params: List[Annotation.AnnotationParameter])
Expand Down
12 changes: 11 additions & 1 deletion scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,17 @@ trait ClassLikeSupport:
.map { _ =>
parseMethod(dd.symbol, kind = Kind.Given(getGivenInstance(dd).map(_.asSignature), None))
}

case dd: DefDef if !dd.symbol.isHiddenByVisibility && dd.symbol.isExported =>
val exportedTarget = dd.rhs.flatMap {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dd.rhs.collect { 
    case a: Apply => a.fun
    case s: Select => s
}

will do the same what flatmap and map

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will change

case a: Apply => Some(a.fun)
case _ => None
}.map {
case s: Select => s
}
val functionName = exportedTarget.fold("instance")(_.name)
val instanceName = exportedTarget.fold("function")(_.qualifier.asInstanceOf[Select].name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it need to a Select? What if we have

object A:
  def a = 1  

object B extends App:                                                                                                                                                                      
     export A._
     

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a wrong assumption that led to exception breaking the scala3doc generation while having object. Fixed it though

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

case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isGiven && !dd.symbol.isSyntheticFunc && !dd.symbol.isExtensionMethod =>
Some(parseMethod(dd.symbol))
Expand Down Expand Up @@ -184,7 +195,6 @@ trait ClassLikeSupport:
case dd: DefDef if !dd.symbol.isClassConstructor && !(dd.symbol.isSuperBridgeMethod || dd.symbol.isDefaultHelperMethod) => dd
case other => other
}

c.membersToDocument.flatMap(parseMember) ++
inherited.flatMap(s => parseInheritedMember(s))
}
Expand Down
2 changes: 2 additions & 0 deletions scala3doc/src/dotty/dokka/tasty/SymOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ class SymOps[Q <: Quotes](val q: Q):

def isGiven: Boolean = sym.flags.is(Flags.Given)

def isExported: Boolean = sym.flags.is(Flags.Exported)

def isExtensionMethod: Boolean = sym.flags.is(Flags.ExtensionMethod)

def isLeftAssoc(d: Symbol): Boolean = !d.name.endsWith(":")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ object FilterAttributes:
case Origin.InheritedFrom(name, _) => Map("inherited" -> name)
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"Exported from $name")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this used? Why is the previous line "from $name", but this one is "Exported from $name", i.e. why is the "Exported" part necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I could add some exports to the test cases.

For this one with Exported from... is my fault, will fix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case _ => Map.empty
case null =>
Map.empty
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ class ScalaPageContentBuilder(
val originInfo = documentable.origin match {
case Origin.ImplicitlyAddedBy(name, dri) => Signature("Implicitly added by ", SLink(name, dri))
case Origin.ExtensionFrom(name, dri) => Signature("Extension method from ", SLink(name, dri))
case Origin.ExportedFrom(name, dri) => Signature("Exported from ", SLink(name, dri))
case _ => Nil
}

Expand Down
4 changes: 4 additions & 0 deletions scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ class ScalaPageCreator(
val (definedTypes, inheritedTypes) = s.membersBy(_.kind.isInstanceOf[Kind.Type])
val (definedGivens, inheritedGives) = s.membersBy(_.kind.isInstanceOf[Kind.Given])
val (definedExtensions, inheritedExtensions) = s.membersBy(_.kind.isInstanceOf[Kind.Extension])
val exports = s.allMembers.filter(_.kind == Kind.Exported)
val (definedImplicits, inheritedImplicits) = s.membersBy(_.kind.isInstanceOf[Kind.Implicit])

b
Expand Down Expand Up @@ -381,6 +382,9 @@ class ScalaPageCreator(
DocumentableGroup(Some("Defined implicits"), definedImplicits),
DocumentableGroup(Some("Inherited implicits"), inheritedImplicits)
)
.documentableTab("Exports")(
DocumentableGroup(Some("Defined exports"), exports)
)


def contentForEnum(c: DClass) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ object ScalaSignatureProvider:
extensionSignature(extension, builder)
case method: DFunction if method.kind.isInstanceOf[Kind.Given] =>
givenMethodSignature(method, builder)
case exprt: DFunction if exprt.kind == Kind.Exported =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need that case and exportedMethodSignature since we handle it as methodSignature anyway ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can delete, but thought it would be more reasonable to state that explicitly

exportedMethodSignature(exprt, builder)
case method: DFunction =>
methodSignature(method, builder)
case enumEntry: DClass if enumEntry.kind == Kind.EnumCase =>
Expand Down Expand Up @@ -138,14 +140,14 @@ object ScalaSignatureProvider:
} else {
extension.getParameters.asScala(0)
}
val withSinature = builder
val withSignature = builder
.modifiersAndVisibility(extension, "def")
.name(extension.getName, extension.getDri)
.generics(extension)
.functionParameters(extension)

if extension.isConstructor then withSinature
else withSinature.text(":").text(" ").typeSignature(extension.getType)
if extension.isConstructor then withSignature
else withSignature.text(":").text(" ").typeSignature(extension.getType)

private def givenMethodSignature(method: DFunction, builder: SignatureBuilder): SignatureBuilder = method.kind match
case Kind.Given(Some(instance), _) =>
Expand All @@ -156,6 +158,8 @@ object ScalaSignatureProvider:
case _ =>
builder.text("given ").name(method.getName, method.getDri)

private def exportedMethodSignature(method: DFunction, builder: SignatureBuilder): SignatureBuilder =
methodSignature(method, builder)

private def methodSignature(method: DFunction, builder: SignatureBuilder): SignatureBuilder =
val bdr = builder
Expand Down