diff --git a/project/Build.scala b/project/Build.scala index 9d233d3dae2f..6c2f8ad966ba 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1506,7 +1506,7 @@ object Build { val scala3version = stdlibVersion(Bootstrapped) // TODO add versions etc. val srcManaged = s"out/bootstrap/stdlib-bootstrapped/scala-$baseVersion/src_managed/main/scala-library-src" - val sourceLinks = s"-source-links:$srcManaged=github://scala/scala/v$scala3version#src/library-source-links:github://lampepfl/dotty" + val sourceLinks = s"-source-links:$srcManaged=github://scala/scala/v$scala3version#src/library" val revision = Seq("-revision", ref, "-project-version", projectVersion) val cmd = Seq("-d", outDir, "-project", name, sourceLinks) ++ revision ++ params ++ targets import _root_.scala.sys.process._ diff --git a/scaladoc/src/dotty/tools/scaladoc/api.scala b/scaladoc/src/dotty/tools/scaladoc/api.scala index 76b6b777e9b1..51f923323826 100644 --- a/scaladoc/src/dotty/tools/scaladoc/api.scala +++ b/scaladoc/src/dotty/tools/scaladoc/api.scala @@ -157,7 +157,18 @@ case class Member( knownChildren: Seq[LinkToType] = Nil, companion: Option[DRI] = None, deprecated: Option[Annotation] = None, -) +): + def needsOwnPage: Boolean = + def properKind(kind: Kind): Boolean = kind match + case Kind.Package => true + case _ if kind.isInstanceOf[Classlike] => true + case Kind.Given(inner, _, _) => properKind(inner) + case Kind.EnumCase(inner) => properKind(inner) + case _ => false + + properKind(kind) && + origin == Origin.RegularlyDefined && + inheritedFrom.isEmpty object Member: def unapply(v: Member): Option[(String, DRI, Visibility, Kind, Origin)] = diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala index 34a792685b92..323a3e3d8816 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/HtmlRenderer.scala @@ -28,22 +28,10 @@ class HtmlRenderer(rootPackage: Member, val members: Map[DRI, Member])(using ctx private val args = summon[DocContext].args val staticSite = summon[DocContext].staticSiteContext - val effectiveMembers = members.filter( (dri, member) => member.origin == Origin.RegularlyDefined && member.inheritedFrom.isEmpty) - - private def needsOwnPage(member: Member): Boolean = - def properKind(kind: Kind): Boolean = kind match - case Kind.Package => true - case _ if kind.isInstanceOf[Classlike] => true - case Kind.Given(inner, _, _) => properKind(inner) - case Kind.EnumCase(inner) => properKind(inner) - case _ => false - - properKind(member.kind) && - member.origin == Origin.RegularlyDefined && - member.inheritedFrom.isEmpty + val effectiveMembers = members private def memberPage(member: Member): Page = - val childrenPages = member.members.filter(needsOwnPage) + val childrenPages = member.members.filter(_.needsOwnPage) Page(Link(member.name, member.dri), member, childrenPages.map(memberPage)) val navigablePage: Page = diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala index 4433bf06ead9..3636f75b56a8 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/MemberRenderer.scala @@ -29,7 +29,7 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext case _ => Nil def inheritedFrom(m: Member) = m.inheritedFrom match - case Some(InheritedFrom(name, dri)) => tableRow("Inhertied from", signatureRenderer.renderLink(name, dri)) + case Some(InheritedFrom(name, dri)) => tableRow("Inherited from", signatureRenderer.renderLink(name, dri)) case _ => Nil def docAttributes(m: Member): Seq[AppliedTag] = @@ -161,7 +161,7 @@ class MemberRenderer(signatureRenderer: SignatureRenderer)(using DocContext) ext ++ filterAttributes.map{ case (n, v) => Attr(s"data-f-$n") := v } div(topLevelAttr:_*)( - a(href:=link(member.dri).getOrElse("#"), cls := "documentableAnchor"), + a(href := (if member.needsOwnPage then link(member.dri).getOrElse("#") else s"#${member.dri.anchor}"), cls := "documentableAnchor"), div(annotations(member)), div(cls := "header monospace")(memberSingnature(member)), div(cls := "docs")( diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 41652c709f74..84f589404c30 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -188,10 +188,22 @@ trait ClassLikeSupport: } private def parseInheritedMember(c: ClassDef)(s: Tree): Option[Member] = - def inheritance = Some(InheritedFrom(s.symbol.owner.normalizedName, s.symbol.owner.dri)) + def inheritance = Some(InheritedFrom(s.symbol.owner.normalizedName, s.symbol.dri)) processTreeOpt(s)(s match case c: ClassDef if c.symbol.shouldDocumentClasslike && !c.symbol.isGiven => Some(parseClasslike(c, signatureOnly = true)) - case other => parseMember(c)(other) + case c: ClassDef if c.symbol.owner.memberMethod(c.name).exists(_.flags.is(Flags.Given)) => Some(parseGivenClasslike(c)) + case other => { + val parsed = parseMember(c)(other) + parsed.map(p => + val parentDRI = c.symbol.dri + p.copy( + dri = p.dri.copy( + location = parentDRI.location, + origin = parentDRI.origin + ) + ) + ) + } ).map(_.copy(inheritedFrom = inheritance)) extension (c: ClassDef) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index 64121556c670..40b8b157bdd2 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -21,7 +21,15 @@ class SymOps[Q <: Quotes](val q: Q): else sym.maybeOwner.className def anchor: Option[String] = - if (!sym.isClassDef && !sym.isPackageDef) Some(sym.name) + if (!sym.isClassDef && !sym.isPackageDef) { + val params = sym.signature.paramSigs.map { + case s: String => s + case i: Int => i.toString + } + val result = sym.signature.resultSig + val hash = ((params.mkString + result).hashCode % 4096).toHexString + Some(s"${sym.name}-$hash") + } else None //TODO: Retrieve string that will match scaladoc anchors diff --git a/scaladoc/test/dotty/tools/scaladoc/ExternalLocationProviderIntegrationTest.scala b/scaladoc/test/dotty/tools/scaladoc/ExternalLocationProviderIntegrationTest.scala index ed2ca7385cdd..f92c3b4ca843 100644 --- a/scaladoc/test/dotty/tools/scaladoc/ExternalLocationProviderIntegrationTest.scala +++ b/scaladoc/test/dotty/tools/scaladoc/ExternalLocationProviderIntegrationTest.scala @@ -33,7 +33,7 @@ class Scaladoc3ExternalLocationProviderIntegrationTest extends ExternalLocationP List(".*scala.*::scaladoc3::https://dotty.epfl.ch/api/"), List( "https://dotty.epfl.ch/api/scala/collection/immutable/Map.html", - "https://dotty.epfl.ch/api/scala/Predef$.html#String", + "https://dotty.epfl.ch/api/scala/Predef$.html#String-0", "https://dotty.epfl.ch/api/scala/util/matching/Regex$$Match.html" ) )