diff --git a/library/src/scala/quoted/Exprs.scala b/library/src/scala/quoted/Exprs.scala index f4504ed2f50d..24e1ed16552f 100644 --- a/library/src/scala/quoted/Exprs.scala +++ b/library/src/scala/quoted/Exprs.scala @@ -5,7 +5,7 @@ object Exprs: /** Matches literal sequence of literal constant value expressions and return a sequence of values. * * Usage: - * ```scala + * ```scala sc:nocompile * inline def sum(args: Int*): Int = ${ sumExpr('args) } * def sumExpr(argsExpr: Expr[Seq[Int]])(using Quotes): Expr[Int] = argsExpr match * case Varargs(Exprs(args)) => diff --git a/project/Build.scala b/project/Build.scala index 21321e60d6d7..65de7af82a48 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -2,6 +2,7 @@ import java.io.File import java.nio.file._ import Modes._ +import ScaladocGeneration._ import com.jsuereth.sbtpgp.PgpKeys import sbt.Keys._ import sbt._ @@ -59,6 +60,8 @@ object DottyJSPlugin extends AutoPlugin { } object Build { + import ScaladocConfigs._ + val referenceVersion = "3.1.2-RC1" val baseVersion = "3.1.3-RC1" @@ -1253,6 +1256,8 @@ object Build { val generateScalaDocumentation = inputKey[Unit]("Generate documentation for dotty lib") val generateTestcasesDocumentation = taskKey[Unit]("Generate documentation for testcases, usefull for debugging tests") + val generateReferenceDocumentation = taskKey[Unit]("Generate language reference documentation for Scala 3") + lazy val `scaladoc-testcases` = project.in(file("scaladoc-testcases")). dependsOn(`scala3-compiler-bootstrapped`). settings(commonBootstrappedSettings) @@ -1287,39 +1292,15 @@ object Build { libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "1.1.0").cross(CrossVersion.for3Use2_13) ) - def generateDocumentation(targets: Seq[String], name: String, outDir: String, ref: String, params: Seq[String] = Nil, includeExternalMappings: Boolean = true) = + def generateDocumentation(configTask: Def.Initialize[Task[GenerationConfig]]) = Def.taskDyn { - val distLocation = (dist / pack).value - val projectVersion = version.value - IO.createDirectory(file(outDir)) - val stdLibVersion = stdlibVersion(NonBootstrapped) - val scalaLib = findArtifactPath(externalCompilerClasspathTask.value, "scala-library") - val dottyLib = (`scala3-library` / Compile / classDirectory).value - // TODO add versions etc. - def srcManaged(v: String, s: String) = s"out/bootstrap/stdlib-bootstrapped/scala-$v/src_managed/main/$s-library-src" - def scalaSrcLink(v: String, s: String) = s"-source-links:${s}github://scala/scala/v$v#src/library" - def dottySrcLink(v: String, sourcesPrefix: String = "", outputPrefix: String = "") = - sys.env.get("GITHUB_SHA") match { - case Some(sha) => - s"-source-links:${sourcesPrefix}github://${sys.env("GITHUB_REPOSITORY")}/$sha$outputPrefix" - case None => s"-source-links:${sourcesPrefix}github://lampepfl/dotty/$v$outputPrefix" - } - - val revision = Seq("-revision", ref, "-project-version", projectVersion) - val cmd = Seq( - "-d", - outDir, - "-project", - name, - scalaSrcLink(stdLibVersion, srcManaged(dottyNonBootstrappedVersion, "scala") + "="), - dottySrcLink(referenceVersion, srcManaged(dottyNonBootstrappedVersion, "dotty") + "=", "#library/src"), - dottySrcLink(referenceVersion), - "-Ygenerate-inkuire", - ) ++ scalacOptionsDocSettings(includeExternalMappings) ++ revision ++ params ++ targets - import _root_.scala.sys.process._ - val escapedCmd = cmd.map(arg => if(arg.contains(" ")) s""""$arg"""" else arg) + val config = configTask.value + config.get[OutputDir].foreach { outDir => + IO.createDirectory(file(outDir.value)) + } + val command = generateCommand(config) Def.task { - (Compile / run).toTask(escapedCmd.mkString(" ", " ", "")).value + (Compile / run).toTask(command).value } } @@ -1363,66 +1344,65 @@ object Build { Test / testcasesSourceRoot := ((`scaladoc-testcases` / baseDirectory).value / "src").getAbsolutePath.toString, run / baseDirectory := (ThisBuild / baseDirectory).value, generateSelfDocumentation := Def.taskDyn { - generateDocumentation( - (Compile / classDirectory).value.getAbsolutePath :: Nil, - "scaladoc", "scaladoc/output/self", VersionUtil.gitHash, Seq("-usejavacp") - ) + generateDocumentation(Scaladoc) }.value, + generateScalaDocumentation := Def.inputTaskDyn { - val extraArgs = spaceDelimited("[output]").parsed - val dest = file(extraArgs.headOption.getOrElse("scaladoc/output/scala3")).getAbsoluteFile - val justAPI = extraArgs.drop(1).headOption == Some("--justAPI") val majorVersion = (LocalProject("scala3-library-bootstrapped") / scalaBinaryVersion).value - val dottyJars: Seq[java.io.File] = Seq( - (`stdlib-bootstrapped`/Compile/products).value, - (`scala3-interfaces`/Compile/products).value, - (`tasty-core-bootstrapped`/Compile/products).value, - ).flatten - - val roots = dottyJars.map(_.getAbsolutePath) - - val managedSources = - (`stdlib-bootstrapped`/Compile/sourceManaged).value / "scala-library-src" - val projectRoot = (ThisBuild/baseDirectory).value.toPath - val stdLibRoot = projectRoot.relativize(managedSources.toPath.normalize()) - val docRootFile = stdLibRoot.resolve("rootdoc.txt") - - val dottyManagesSources = - (`stdlib-bootstrapped`/Compile/sourceManaged).value / "dotty-library-src" - - val dottyLibRoot = projectRoot.relativize(dottyManagesSources.toPath.normalize()) - - def generateDocTask = - generateDocumentation( - roots, "Scala 3", dest.getAbsolutePath, "main", - Seq( - "-comment-syntax", "wiki", - s"-source-links:docs=github://lampepfl/dotty/main#docs", - "-doc-root-content", docRootFile.toString, - "-versions-dictionary-url", - "https://scala-lang.org/api/versions.json", - "-Ydocument-synthetic-types", - s"-snippet-compiler:${dottyLibRoot}/scala/quoted=compile,${dottyLibRoot}/scala/compiletime=compile" - ) ++ (if (justAPI) Nil else Seq("-siteroot", "docs", "-Yapi-subdirectory")), includeExternalMappings = false) - - if (dottyJars.isEmpty) Def.task { streams.value.log.error("Dotty lib wasn't found") } - else if (justAPI) generateDocTask - else Def.task{ - IO.write(dest / "versions" / "latest-nightly-base", majorVersion) - - // This file is used by GitHub Pages when the page is available in a custom domain - IO.write(dest / "CNAME", "dotty.epfl.ch") - }.dependsOn(generateDocTask) + + val extraArgs = spaceDelimited("[] [--justAPI]").parsed + val outputDirOverride = extraArgs.headOption.fold(identity[GenerationConfig](_))(newDir => { + config: GenerationConfig => config.add(OutputDir(newDir)) + }) + val justAPIArg: Option[String] = extraArgs.drop(1).find(_ == "--justAPI") + val justAPI = justAPIArg.fold(identity[GenerationConfig](_))(_ => { + config: GenerationConfig => config.remove[SiteRoot] + }) + val overrideFunc = outputDirOverride.andThen(justAPI) + + val config = Def.task { + overrideFunc(Scala3.value) + } + + val writeAdditionalFiles = Def.task { + val dest = file(config.value.get[OutputDir].get.value) + if (justAPIArg.isEmpty) { + IO.write(dest / "versions" / "latest-nightly-base", majorVersion) + // This file is used by GitHub Pages when the page is available in a custom domain + IO.write(dest / "CNAME", "dotty.epfl.ch") + } + } + + writeAdditionalFiles.dependsOn(generateDocumentation(config)) }.evaluated, generateTestcasesDocumentation := Def.taskDyn { - generateDocumentation( - (Test / Build.testcasesOutputDir).value, - "scaladoc testcases", - "scaladoc/output/testcases", - "main", - Seq("-usejavacp", "-snippet-compiler:scaladoc-testcases/docs=compile", "-siteroot", "scaladoc-testcases/docs") + generateDocumentation(Testcases) + }.value, + + generateReferenceDocumentation := Def.taskDyn { + val temp = IO.createTemporaryDirectory + IO.copyDirectory(file("docs"), temp / "docs") + IO.delete(temp / "docs" / "_blog") + + IO.copyDirectory( + file("project") / "resources" / "referenceReplacements", + temp / "docs", + overwrite = true ) + + val languageReferenceConfig = Def.task { + Scala3.value + .add(OutputDir("scaladoc/output/reference")) + .add(SiteRoot(s"${temp.getAbsolutePath}/docs")) + .add(ProjectName("Scala 3 Reference")) + .add(SourceLinks(List( + dottySrcLink(referenceVersion, temp.getAbsolutePath + "=") + ))) + .withTargets(List("___fake___.scala")) + } + + generateDocumentation(languageReferenceConfig) }.value, Test / buildInfoKeys := Seq[BuildInfoKey]( @@ -1803,3 +1783,123 @@ object Build { }) } } + +object ScaladocConfigs { + import Build._ + private lazy val currentYear: String = java.util.Calendar.getInstance().get(java.util.Calendar.YEAR).toString + + def dottyExternalMapping = ".*scala/.*::scaladoc3::https://dotty.epfl.ch/api/" + def javaExternalMapping = ".*java/.*::javadoc::https://docs.oracle.com/javase/8/docs/api/" + def scalaSrcLink(v: String, s: String) = s"${s}github://scala/scala/v$v#src/library" + def dottySrcLink(v: String, sourcesPrefix: String = "", outputPrefix: String = "") = + sys.env.get("GITHUB_SHA") match { + case Some(sha) => + s"${sourcesPrefix}github://${sys.env("GITHUB_REPOSITORY")}/$sha$outputPrefix" + case None => s"${sourcesPrefix}github://lampepfl/dotty/$v$outputPrefix" + } + + lazy val DefaultGenerationConfig = Def.task { + def distLocation = (dist / pack).value + def projectVersion = version.value + def stdLibVersion = stdlibVersion(NonBootstrapped) + def scalaLib = findArtifactPath(externalCompilerClasspathTask.value, "scala-library") + def dottyLib = (`scala3-library` / Compile / classDirectory).value + def srcManaged(v: String, s: String) = s"out/bootstrap/stdlib-bootstrapped/scala-$v/src_managed/main/$s-library-src" + + def defaultSourceLinks: SourceLinks = SourceLinks( + List( + scalaSrcLink(stdLibVersion, srcManaged(dottyNonBootstrappedVersion, "scala") + "="), + dottySrcLink(referenceVersion, srcManaged(dottyNonBootstrappedVersion, "dotty") + "=", "#library/src"), + dottySrcLink(referenceVersion), + "docs=github://lampepfl/dotty/main#docs" + ) + ) + def socialLinks = SocialLinks(List( + "github::https://github.com/lampepfl/dotty", + "discord::https://discord.com/invite/scala", + "twitter::https://twitter.com/scala_lang", + )) + def projectLogo = ProjectLogo("docs/_assets/images/logo.svg") + def skipByRegex = SkipByRegex(List(".+\\.internal($|\\..+)", ".+\\.impl($|\\..+)")) + def skipById = SkipById(List( + "scala.runtime.stdLibPatches", + "scala.runtime.MatchCase" + )) + def projectFooter = ProjectFooter(s"Copyright (c) 2002-$currentYear, LAMP/EPFL") + def defaultTemplate = DefaultTemplate("static-site-main") + GenerationConfig( + List(), + ProjectVersion(projectVersion), + GenerateInkuire(true), + defaultSourceLinks, + skipByRegex, + skipById, + projectLogo, + socialLinks, + projectFooter, + defaultTemplate, + Author(true), + Groups(true) + ) + } + + lazy val Scaladoc = Def.task { + DefaultGenerationConfig.value + .add(UseJavacp(true)) + .add(ProjectName("scaladoc")) + .add(OutputDir("scaladoc/output/self")) + .add(Revision(VersionUtil.gitHash)) + .add(ExternalMappings(List(dottyExternalMapping, javaExternalMapping))) + .withTargets((Compile / classDirectory).value.getAbsolutePath :: Nil) + } + + lazy val Testcases = Def.task { + val tastyRoots = (Test / Build.testcasesOutputDir).value + DefaultGenerationConfig.value + .add(UseJavacp(true)) + .add(OutputDir("scaladoc/output/testcases")) + .add(ProjectName("scaladoc testcases")) + .add(Revision("main")) + .add(SnippetCompiler(List("scaladoc-testcases/docs=compile"))) + .add(SiteRoot("scaladoc-testcases/docs")) + .add(ExternalMappings(List(dottyExternalMapping, javaExternalMapping))) + .withTargets(tastyRoots) + } + + lazy val Scala3 = Def.task { + val dottyJars: Seq[java.io.File] = Seq( + (`stdlib-bootstrapped`/Compile/products).value, + (`scala3-interfaces`/Compile/products).value, + (`tasty-core-bootstrapped`/Compile/products).value, + ).flatten + + val roots = dottyJars.map(_.getAbsolutePath) + + val managedSources = + (`stdlib-bootstrapped`/Compile/sourceManaged).value / "scala-library-src" + val projectRoot = (ThisBuild/baseDirectory).value.toPath + val stdLibRoot = projectRoot.relativize(managedSources.toPath.normalize()) + val docRootFile = stdLibRoot.resolve("rootdoc.txt") + + val dottyManagesSources = + (`stdlib-bootstrapped`/Compile/sourceManaged).value / "dotty-library-src" + + val dottyLibRoot = projectRoot.relativize(dottyManagesSources.toPath.normalize()) + DefaultGenerationConfig.value + .add(ProjectName("Scala 3")) + .add(OutputDir(file("scaladoc/output/scala3").getAbsoluteFile.getAbsolutePath)) + .add(Revision("main")) + .add(ExternalMappings(List(javaExternalMapping))) + .add(DocRootContent(docRootFile.toString)) + .add(CommentSyntax("wiki")) + .add(VersionsDictionaryUrl("https://scala-lang.org/api/versions.json")) + .add(DocumentSyntheticTypes(true)) + .add(SnippetCompiler(List( + s"${dottyLibRoot}/scala/quoted=compile", + s"${dottyLibRoot}/scala/compiletime=compile" + ))) + .add(SiteRoot("docs")) + .add(ApiSubdirectory(true)) + .withTargets(roots) + } +} \ No newline at end of file diff --git a/project/ScaladocGeneration.scala b/project/ScaladocGeneration.scala new file mode 100644 index 000000000000..bce20b23ec37 --- /dev/null +++ b/project/ScaladocGeneration.scala @@ -0,0 +1,181 @@ +import sbt._ +import Build._ + +object ScaladocGeneration { + def generateCommand(config: GenerationConfig): String = + " " + config.serialize + + sealed trait Arg[T] { + def key: String + def value: T + + def serialize: String = + value match { + case s: String => s"$key ${escape(s)}" + case true => s"$key" + case list: List[String] => s"$key:${list.map(escape).mkString(",")}" + case _ => + println(s"Unsupported setting: $key -> $value") + "" + } + + private def escape(s: String) = if(s.contains(" ")) s""""$s"""" else s + } + case class ProjectName(value: String) extends Arg[String] { + def key: String = "-project" + } + + case class OutputDir(value: String) extends Arg[String] { + def key: String = "-d" + } + + case class ProjectVersion(value: String) extends Arg[String] { + def key: String = "-project-version" + } + + case class ProjectLogo(value: String) extends Arg[String] { + def key: String = "-project-logo" + } + + case class ProjectFooter(value: String) extends Arg[String] { + def key: String = "-project-footer" + } + + case class SourceLinks(value: List[String]) extends Arg[List[String]] { + def key: String = "-source-links" + } + + case class CommentSyntax(value: String) extends Arg[String] { + def key: String = "-comment-syntax" + } + + case class Revision(value: String) extends Arg[String] { + def key: String = "-revision" + } + + case class ExternalMappings(value: List[String]) extends Arg[List[String]] { + def key: String = "-external-mappings" + } + + case class SocialLinks(value: List[String]) extends Arg[List[String]] { + def key: String = "-social-links" + } + + case class SkipPackages(value: List[String]) extends Arg[List[String]] { + def key: String = "-skip-packages" + } + + case class SkipById(value: List[String]) extends Arg[List[String]] { + def key: String = "-skip-by-id" + } + + case class SkipByRegex(value: List[String]) extends Arg[List[String]] { + def key: String = "-skip-by-regex" + } + + case class DocRootContent(value: String) extends Arg[String] { + def key: String = "-doc-root-content" + } + + case class Author(value: Boolean) extends Arg[Boolean] { + def key: String = "-author" + } + + case class Groups(value: Boolean) extends Arg[Boolean] { + def key: String = "-groups" + } + + case class DocCanonicalBaseUrl(value: String) extends Arg[String] { + def key: String = "-doc-canonical-base-url" + } + + case class SiteRoot(value: String) extends Arg[String] { + def key: String = "-siteroot" + } + + case class NoLinkWarnings(value: Boolean) extends Arg[Boolean] { + def key: String = "-no-link-warnings" + } + + case class VersionsDictionaryUrl(value: String) extends Arg[String] { + def key: String = "-versions-dictionary-url" + } + + case class DocumentSyntheticTypes(value: Boolean) extends Arg[Boolean] { + def key: String = "-Ydocument-synthetic-types" + } + + case class SnippetCompiler(value: List[String]) extends Arg[List[String]] { + def key: String = "-snippet-compiler" + } + + case class GenerateInkuire(value: Boolean) extends Arg[Boolean] { + def key: String = "-Ygenerate-inkuire" + } + + case class ApiSubdirectory(value: Boolean) extends Arg[Boolean] { + def key: String = "-Yapi-subdirectory" + } + + case class ScastieConfiguration(value: String) extends Arg[String] { + def key: String = "-scastie-configuration" + } + + case class DefaultTemplate(value: String) extends Arg[String] { + def key: String = "-default-template" + } + + case class UseJavacp(value: Boolean) extends Arg[Boolean] { + def key: String = "-usejavacp" + } + + import _root_.scala.reflect._ + + trait GenerationConfig { + def get[T <: Arg[_] : ClassTag]: Option[T] + def add[T <: Arg[_]](arg: T): GenerationConfig + def remove[T <: Arg[_]: ClassTag]: GenerationConfig + def withTargets(targets: Seq[String]): GenerationConfig + def serialize: String + } + + object GenerationConfig { + def apply(): GenerationConfig = GenerationConfigImpl(Seq.empty, Seq.empty) + def apply(targets: List[String], args: Arg[_]*): GenerationConfig = args.foldLeft(GenerationConfig()) { (config, elem) => + config.add(elem) + } + private case class GenerationConfigImpl(targets: Seq[String], args: Seq[Arg[_]]) extends GenerationConfig { + override def add[T <: Arg[_]](arg: T): GenerationConfig = { + implicit val tag: ClassTag[T] = ClassTag(arg.getClass) + val (removedElem, argsWithoutElem) = argsWithout[T](tag) + removedElem.foreach(elem => println(s"$elem has been overwritten by $arg")) + GenerationConfigImpl(targets, argsWithoutElem :+ arg) + } + override def remove[T <: Arg[_] : ClassTag]: GenerationConfig = { + GenerationConfigImpl(targets, argsWithout[T]._2) + } + + override def get[T <: Arg[_] : ClassTag]: Option[T] = { + val tag = implicitly[ClassTag[T]] + args.collect { + case tag(t) => t + }.headOption + } + + override def withTargets(targets: Seq[String]) = copy(targets = targets) + override def serialize: String = ( + args + .map(_.serialize) + ++ targets + ).mkString(" ") + + private def argsWithout[T <: Arg[_]]( + implicit tag: ClassTag[T] + ): (Option[T], Seq[Arg[_]]) = args.foldLeft[(Option[T], Seq[Arg[_]])]((None, Seq.empty)) { + case ((removedElem, rest), tag(t)) => (Some(t), rest) + case ((removedElem, rest), elem) => (removedElem, rest :+ elem) + } + } + } + +} \ No newline at end of file diff --git a/project/resources/referenceReplacements/_layouts/static-site-main.html b/project/resources/referenceReplacements/_layouts/static-site-main.html new file mode 100644 index 000000000000..d47907819956 --- /dev/null +++ b/project/resources/referenceReplacements/_layouts/static-site-main.html @@ -0,0 +1,44 @@ +--- +layout: main +--- +
+ + {{ content }} + +
diff --git a/project/resources/referenceReplacements/sidebar.yml b/project/resources/referenceReplacements/sidebar.yml new file mode 100644 index 000000000000..7d43febb562f --- /dev/null +++ b/project/resources/referenceReplacements/sidebar.yml @@ -0,0 +1,139 @@ +index: reference/overview.md +subsection: + - page: reference/overview.md + - title: New Types + index: reference/new-types/new-types.md + subsection: + - page: reference/new-types/intersection-types.md + - page: reference/new-types/intersection-types-spec.md + - page: reference/new-types/union-types.md + - page: reference/new-types/union-types-spec.md + - page: reference/new-types/type-lambdas.md + - page: reference/new-types/type-lambdas-spec.md + - page: reference/new-types/match-types.md + - page: reference/new-types/dependent-function-types.md + - page: reference/new-types/dependent-function-types-spec.md + - page: reference/new-types/polymorphic-function-types.md + - title: Enums + index: reference/enums/enums-index.md + subsection: + - page: reference/enums/enums.md + - page: reference/enums/adts.md + - page: reference/enums/desugarEnums.md + - title: Contextual Abstractions + index: reference/contextual/contextual.md + directory: contextual + subsection: + - page: reference/contextual/givens.md + - page: reference/contextual/using-clauses.md + - page: reference/contextual/context-bounds.md + - page: reference/contextual/given-imports.md + - page: reference/contextual/extension-methods.md + - page: reference/contextual/right-associative-extension-methods.md + - page: reference/contextual/type-classes.md + - page: reference/contextual/derivation.md + - page: reference/contextual/derivation-macro.md + - page: reference/contextual/multiversal-equality.md + - page: reference/contextual/context-functions.md + - page: reference/contextual/context-functions-spec.md + - page: reference/contextual/conversions.md + - page: reference/contextual/by-name-context-parameters.md + - page: reference/contextual/relationship-implicits.md + - title: Metaprogramming + index: reference/metaprogramming/metaprogramming.md + subsection: + - page: reference/metaprogramming/inline.md + - page: reference/metaprogramming/compiletime-ops.md + - page: reference/metaprogramming/macros.md + - page: reference/metaprogramming/macros-spec.md + - page: reference/metaprogramming/staging.md + - page: reference/metaprogramming/reflection.md + - page: reference/metaprogramming/tasty-inspect.md + - title: Other New Features + index: reference/other-new-features/other-new-types.md + subsection: + - page: reference/other-new-features/trait-parameters.md + - page: reference/other-new-features/transparent-traits.md + - page: reference/other-new-features/creator-applications.md + - page: reference/other-new-features/export.md + - page: reference/other-new-features/opaques.md + - page: reference/other-new-features/opaques-details.md + - page: reference/other-new-features/open-classes.md + - page: reference/other-new-features/parameter-untupling.md + - page: reference/other-new-features/parameter-untupling-spec.md + - page: reference/other-new-features/kind-polymorphism.md + - page: reference/other-new-features/matchable.md + - page: reference/other-new-features/threadUnsafe-annotation.md + - page: reference/other-new-features/targetName.md + - page: reference/other-new-features/control-syntax.md + - page: reference/other-new-features/indentation.md + - page: reference/other-new-features/safe-initialization.md + - page: reference/other-new-features/type-test.md + - page: reference/other-new-features/experimental-defs.md + - title: Other Changed Features + directory: changed-features + index: reference/changed-features/changed-features.md + subsection: + - page: reference/changed-features/numeric-literals.md + - page: reference/changed-features/structural-types.md + - page: reference/changed-features/structural-types-spec.md + - page: reference/changed-features/operators.md + - page: reference/changed-features/wildcards.md + - page: reference/changed-features/imports.md + - page: reference/changed-features/type-checking.md + - page: reference/changed-features/type-inference.md + - page: reference/changed-features/implicit-resolution.md + - page: reference/changed-features/implicit-conversions.md + - page: reference/changed-features/implicit-conversions-spec.md + - page: reference/changed-features/overload-resolution.md + - page: reference/changed-features/match-syntax.md + - page: reference/changed-features/vararg-splices.md + - page: reference/changed-features/pattern-bindings.md + - page: reference/changed-features/pattern-matching.md + - page: reference/changed-features/eta-expansion.md + - page: reference/changed-features/eta-expansion-spec.md + - page: reference/changed-features/compiler-plugins.md + - page: reference/changed-features/lazy-vals-init.md + - page: reference/changed-features/main-functions.md + - title: Dropped Features + index: reference/dropped-features/dropped-features.md + subsection: + - page: reference/dropped-features/delayed-init.md + - page: reference/dropped-features/macros.md + - page: reference/dropped-features/existential-types.md + - page: reference/dropped-features/type-projection.md + - page: reference/dropped-features/do-while.md + - page: reference/dropped-features/procedure-syntax.md + - page: reference/dropped-features/package-objects.md + - page: reference/dropped-features/early-initializers.md + - page: reference/dropped-features/class-shadowing.md + - page: reference/dropped-features/class-shadowing-spec.md + - page: reference/dropped-features/limit22.md + - page: reference/dropped-features/xml.md + - page: reference/dropped-features/symlits.md + - page: reference/dropped-features/auto-apply.md + - page: reference/dropped-features/weak-conformance.md + - page: reference/dropped-features/weak-conformance-spec.md + - page: reference/dropped-features/nonlocal-returns.md + - page: reference/dropped-features/this-qualifier.md + - page: reference/dropped-features/wildcard-init.md + - title: Experimental Features + directory: experimental + subsection: + - page: reference/experimental/overview.md + - page: reference/experimental/canthrow.md + - page: reference/experimental/erased-defs.md + - page: reference/experimental/erased-defs-spec.md + - page: reference/experimental/named-typeargs.md + - page: reference/experimental/named-typeargs-spec.md + - page: reference/experimental/numeric-literals.md + - page: reference/experimental/explicit-nulls.md + - page: reference/experimental/cc.md + - page: reference/syntax.md + - title: Language Versions + index: reference/language-versions/language-versions.md + subsection: + - page: reference/language-versions/source-compatibility.md + - page: reference/language-versions/binary-compatibility.md + - page: reference/soft-modifier.md + - page: reference/features-classification.md \ No newline at end of file diff --git a/scaladoc/src/dotty/tools/scaladoc/PathBased.scala b/scaladoc/src/dotty/tools/scaladoc/PathBased.scala index 231fe8989c26..ab73fc683846 100644 --- a/scaladoc/src/dotty/tools/scaladoc/PathBased.scala +++ b/scaladoc/src/dotty/tools/scaladoc/PathBased.scala @@ -4,9 +4,7 @@ import java.nio.file.{Path, Paths} case class PathBased[T](entries: List[PathBased.Entry[T]], projectRoot: Path): def get(path: Path): Option[PathBased.Result[T]] = - if path.isAbsolute then - if path.startsWith(projectRoot) then get(projectRoot.relativize(path)) - else None + if path.isAbsolute && path.startsWith(projectRoot) then get(projectRoot.relativize(path)) else entries.filter(_.path.forall(p => path.startsWith(p))).maxByOption(_.path.map(_.toString.length)).map(entry => PathBased.Result(entry.path.fold(path)(_.relativize(path)), entry.elem) ) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala index 45a080d4828a..913b40c4dd41 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/Renderer.scala @@ -83,7 +83,9 @@ abstract class Renderer(rootPackage: Member, val members: Map[DRI, Member], prot then rootPckPage.withTitle(args.name) else { val newRootPage = templateToPage(newRoot, siteContext) - newRootPage.withNewChildren(Seq(rootPckPage.withTitle("API"))) + newRootPage.withNewChildren( + Seq(rootPckPage.withTitle("API")).filter(_ => rootPackage.members.nonEmpty) + ) } val redirectPages: Seq[Page] = staticSite.fold(Seq.empty)(siteContext => siteContext.redirectTemplates.map {