diff --git a/.github/workflows/scala3doc.yaml b/.github/workflows/scala3doc.yaml
index ad9d29a3c298..440cd6c8753f 100644
--- a/.github/workflows/scala3doc.yaml
+++ b/.github/workflows/scala3doc.yaml
@@ -62,3 +62,36 @@ jobs:
echo uplading docs to https://scala3doc.virtuslab.com/$DOC_DEST
az storage container create --name $DOC_DEST --account-name scala3docstorage --public-access container
az storage blob sync -s scala3doc/output -c $DOC_DEST --account-name scala3docstorage
+
+ community-docs:
+ env:
+ AZURE_STORAGE_SAS_TOKEN: ${{ secrets.AZURE_STORAGE_SAS_TOKEN }}
+ runs-on: ubuntu-latest
+ if: "github.event_name == 'pull_request' || contains(github.event.ref, 'scala3doc') || contains(github.event.ref, 'master')"
+
+ steps:
+ - name: Git Checkout
+ uses: actions/checkout@v2
+
+ - name: Set up JDK 8
+ uses: actions/setup-java@v1
+ with:
+ java-version: 8
+
+ - name: Init submodules
+ run: git submodule update --init --recursive --jobs 7
+
+ - name: Generate docs
+ run: ./project/scripts/sbt "community-build/run doc all docsOutput"
+
+ - name: Upload documentation to server
+ uses: azure/CLI@v1
+ if: env.AZURE_STORAGE_SAS_TOKEN
+ env:
+ PR_NUMBER: ${{ github.event.pull_request.number }}
+ with:
+ inlineScript: |
+ DOC_DEST=pr-${PR_NUMBER:-${GITHUB_REF##*/}}-docs
+ echo uplading docs to https://scala3doc.virtuslab.com/$DOC_DEST
+ az storage container create --name $DOC_DEST --account-name scala3docstorage --public-access container
+ az storage blob sync -s community-build/docsOutput -c $DOC_DEST --account-name scala3docstorage
diff --git a/community-build/src/scala/dotty/communitybuild/Fields.scala b/community-build/src/scala/dotty/communitybuild/Fields.scala
new file mode 100644
index 000000000000..bbf729418a6b
--- /dev/null
+++ b/community-build/src/scala/dotty/communitybuild/Fields.scala
@@ -0,0 +1,9 @@
+package dotty.communitybuild
+
+import scala.quoted.Type
+
+class FieldsDsl[V](v: V):
+ inline def of[T]: Seq[T] = FieldsImpl.fieldsOfType[V, T](v)
+
+extension [V](on: V):
+ def fields = FieldsDsl(on)
\ No newline at end of file
diff --git a/community-build/src/scala/dotty/communitybuild/FieldsImpl.scala b/community-build/src/scala/dotty/communitybuild/FieldsImpl.scala
new file mode 100644
index 000000000000..2d7124727af2
--- /dev/null
+++ b/community-build/src/scala/dotty/communitybuild/FieldsImpl.scala
@@ -0,0 +1,17 @@
+package dotty.communitybuild
+
+import scala.quoted._
+
+object FieldsImpl:
+ inline def fieldsOfType[V, T](inline v: V): Seq[T] =
+ ${ fieldsImpl[V, T]('v) }
+
+ def fieldsImpl[V: Type, T: Type](from: Expr[V])(using Quotes): Expr[Seq[T]] =
+ import quotes.reflect._
+ val retType = TypeTree.of[T].tpe
+ def isProjectField(s: Symbol) =
+ s.isValDef && s.tree.asInstanceOf[ValDef].tpt.tpe <:< retType
+ val projectsTree = Term.of(from)
+ val symbols = TypeTree.of[V].symbol.members.filter(isProjectField)
+ val selects = symbols.map(Select(projectsTree, _).asExprOf[T])
+ '{ println(${Expr(retType.show)}); ${Varargs(selects)} }
diff --git a/community-build/src/scala/dotty/communitybuild/Main.scala b/community-build/src/scala/dotty/communitybuild/Main.scala
index 62f1b8a29159..13c9ae573772 100644
--- a/community-build/src/scala/dotty/communitybuild/Main.scala
+++ b/community-build/src/scala/dotty/communitybuild/Main.scala
@@ -1,13 +1,91 @@
package dotty.communitybuild
-object Main {
- /** Builds stdlib.
- *
- * Output is available in build/pack/lib directory in stdlib project.
- *
- * In the future, we allow building different projects based on arguments,
- * but for now stdlib is the only usecase.
- */
+import java.nio.file.Paths
+import java.nio.file.Path
+import java.nio.file.Files
+import scala.sys.process._
+
+
+object Main:
+
+ private def generateDocs(project: CommunityProject): Seq[Path] =
+ val name = project.project
+ try
+ project.doc()
+ val pathsOut = s"find community-projects/$name/ -name 'scala3doc.version'".!!
+ pathsOut.linesIterator.map(Paths.get(_).getParent).toList
+ catch
+ case e: Exception =>
+ e.printStackTrace()
+ Nil
+
+ /** Allows running various commands on community build projects. */
def main(args: Array[String]): Unit =
- projects.stdLib213.publish()
-}
+ args.toList match
+ case "publish" :: name :: Nil =>
+ case "doc" :: "all" :: destStr :: Nil =>
+ val dest = Paths.get(destStr)
+ Seq("rm", "-rf", "destStr").!
+ Files.createDirectory(dest)
+ val (toRun, ignored) =
+ allProjects.partition(_.docCommand != null)
+
+ val paths = toRun.map { project =>
+ val name = project.project
+ val projectDest = dest.resolve(name)
+ val projectRoot = Paths.get(s"community-projects/$name")
+ println(s"generating docs for $name into $projectDest")
+ val generatedDocs = generateDocs(project)
+ if !Files.exists(projectDest) && generatedDocs.nonEmpty then
+ Files.createDirectory(projectDest)
+
+ val docsFiles = generatedDocs.map { docsPath =>
+ val destFileName =
+ docsPath.subpath(2, docsPath.getNameCount).toString.replace('/', '_')
+
+ Seq("cp", "-r", docsPath.toString, projectDest.resolve(destFileName).toString).!
+ destFileName
+ }
+ name -> docsFiles
+ }
+
+ val (failed, withDocs) = paths.partition{ case (_, paths) => paths.isEmpty }
+
+ val indexFile = withDocs.map { case (name, paths) =>
+ paths.map(p => s"""$p\n""")
+ .mkString(s"
$name
","\n", "\n")
+ }.mkString("\n", "\n", "\n")
+
+ Files.write(dest.resolve("index.html"), indexFile.getBytes)
+
+ if ignored.nonEmpty then
+ println(s"Ignored project without doc command: ${ignored.map(_.project)}")
+
+ if failed.nonEmpty then
+ println(s"Documentation not found for ${failed.map(_._1).mkString(", ")}")
+ sys.exit(1)
+
+ case "doc" :: names if names.nonEmpty =>
+ val missing = names.filterNot(projectMap.contains)
+ if missing.nonEmpty then
+ println(s"Missing projects: ${missing.mkString(", ")}. All projects: ${allProjects.mkString(", ")}")
+ sys.exit(1)
+
+ val failed = names.filter{ p =>
+ val docsRoots = generateDocs(projectMap(p))
+ if docsRoots.nonEmpty then println(s"Docs for $p generated in $docsRoots")
+ docsRoots.isEmpty
+ }
+ if failed.nonEmpty then
+ println(s"Documentation not found for ${failed.mkString(", ")}")
+ sys.exit(1)
+
+ case args =>
+ println("USAGE: ")
+ println("COMMAND is one of: publish doc")
+ println("Available projects are:")
+ allProjects.foreach { k =>
+ println(s"\t$k")
+ }
+ sys.exit(1)
+
diff --git a/community-build/src/scala/dotty/communitybuild/projects.scala b/community-build/src/scala/dotty/communitybuild/projects.scala
index 788735b7738f..1c252d5165eb 100644
--- a/community-build/src/scala/dotty/communitybuild/projects.scala
+++ b/community-build/src/scala/dotty/communitybuild/projects.scala
@@ -45,16 +45,20 @@ sealed trait CommunityProject:
val project: String
val testCommand: String
val publishCommand: String
+ val docCommand: String
val dependencies: List[CommunityProject]
val binaryName: String
val runCommandsArgs: List[String] = Nil
final val projectDir = communitybuildDir.resolve("community-projects").resolve(project)
+ final def publishDependencies(): Unit =
+ dependencies.foreach(_.publish())
+
/** Publish this project to the local Maven repository */
final def publish(): Unit =
if !published then
- dependencies.foreach(_.publish())
+ publishDependencies()
log(s"Publishing $project")
if publishCommand eq null then
throw RuntimeException(s"Publish command is not specified for $project. Project details:\n$this")
@@ -62,6 +66,16 @@ sealed trait CommunityProject:
if exitCode != 0 then
throw RuntimeException(s"Publish command exited with code $exitCode for project $project. Project details:\n$this")
published = true
+
+ final def doc(): Unit =
+ publishDependencies()
+ log(s"Documenting $project")
+ if docCommand eq null then
+ throw RuntimeException(s"Doc command is not specified for $project. Project details:\n$this")
+ val exitCode = exec(projectDir, binaryName, (runCommandsArgs :+ docCommand): _*)
+ if exitCode != 0 then
+ throw RuntimeException(s"Doc command exited with code $exitCode for project $project. Project details:\n$this")
+
end CommunityProject
final case class MillCommunityProject(
@@ -71,6 +85,7 @@ final case class MillCommunityProject(
override val binaryName: String = "./mill"
override val testCommand = s"$baseCommand.test"
override val publishCommand = s"$baseCommand.publishLocal"
+ override val docCommand = null
override val runCommandsArgs = List("-i", "-D", s"dottyVersion=$compilerVersion")
final case class SbtCommunityProject(
@@ -78,7 +93,9 @@ final case class SbtCommunityProject(
sbtTestCommand: String,
extraSbtArgs: List[String] = Nil,
dependencies: List[CommunityProject] = Nil,
- sbtPublishCommand: String = null) extends CommunityProject:
+ sbtPublishCommand: String = null,
+ sbtDocCommand: String = null
+ ) extends CommunityProject:
override val binaryName: String = "sbt"
// A project in the community build can depend on an arbitrary version of
@@ -105,7 +122,11 @@ final case class SbtCommunityProject(
++ s"++$compilerVersion!; "
override val testCommand = s"$baseCommand$sbtTestCommand"
- override val publishCommand = s"$baseCommand$sbtPublishCommand"
+ override val publishCommand = if sbtPublishCommand eq null then null else s"$baseCommand$sbtPublishCommand"
+ override val docCommand =
+ if sbtDocCommand eq null then null else
+ val cmd = if sbtDocCommand.startsWith(";") then sbtDocCommand else s";$sbtDocCommand"
+ s"$baseCommand set every useScala3doc := true; set every doc/logLevel := Level.Warn $cmd "
override val runCommandsArgs: List[String] =
// Run the sbt command with the compiler version and sbt plugin set in the build
@@ -119,6 +140,17 @@ final case class SbtCommunityProject(
)
object projects:
+
+ private def forceDoc(projects: String*) =
+ projects.map(project =>
+ s""";set $project/Compile/doc/sources ++= ($project/Compile/doc/tastyFiles).value ;$project/doc"""
+ ).mkString(" ")
+
+ private def aggregateDoc(in: String)(projects: String*) =
+ val tastyFiles =
+ (in +: projects).map(p => s"($p/Compile/doc/tastyFiles).value").mkString(" ++ ")
+ s""";set $in/Compile/doc/sources ++= file("a.scala") +: ($tastyFiles) ;$in/doc"""
+
lazy val utest = MillCommunityProject(
project = "utest",
baseCommand = s"utest.jvm[$compilerVersion]",
@@ -191,61 +223,81 @@ object projects:
lazy val intent = SbtCommunityProject(
project = "intent",
sbtTestCommand = "test",
+ sbtDocCommand = "doc"
)
lazy val algebra = SbtCommunityProject(
project = "algebra",
sbtTestCommand = "coreJVM/compile",
+ sbtDocCommand = forceDoc("coreJVM")
)
lazy val scalacheck = SbtCommunityProject(
project = "scalacheck",
sbtTestCommand = "jvm/test;js/test",
- sbtPublishCommand = "jvm/publishLocal;js/publishLocal"
+ sbtPublishCommand = "jvm/publishLocal;js/publishLocal",
+ sbtDocCommand = forceDoc("jvm")
)
lazy val scalatest = SbtCommunityProject(
project = "scalatest",
sbtTestCommand = "scalacticDotty/clean;scalacticTestDotty/test; scalatestTestDotty/test",
- sbtPublishCommand = "scalacticDotty/publishLocal; scalatestDotty/publishLocal"
+ sbtPublishCommand = "scalacticDotty/publishLocal; scalatestDotty/publishLocal",
+ sbtDocCommand = ";scalacticDotty/doc" // fails with missing type ;scalatestDotty/doc"
+ // cannot take signature of (test: org.scalatest.concurrent.ConductorFixture#OneArgTest):
+ // org.scalatest.Outcome
+ // Problem parsing scalatest.dotty/target/scala-3.0.0-M2/src_managed/main/org/scalatest/concurrent/ConductorFixture.scala:[602..624..3843], documentation may not be generated.
+ // dotty.tools.dotc.core.MissingType:
)
lazy val scalatestplusScalacheck = SbtCommunityProject(
project = "scalatestplus-scalacheck",
sbtTestCommand = "scalatestPlusScalaCheckJVM/test",
sbtPublishCommand = "scalatestPlusScalaCheckJVM/publishLocal",
+ sbtDocCommand = "scalatestPlusScalaCheckJVM/doc",
dependencies = List(scalatest, scalacheck)
)
lazy val scalaXml = SbtCommunityProject(
project = "scala-xml",
sbtTestCommand = "xml/test",
+ sbtDocCommand = "xml/doc"
)
lazy val scalap = SbtCommunityProject(
project = "scalap",
sbtTestCommand = "scalap/compile",
+ sbtDocCommand = "scalap/doc"
)
lazy val betterfiles = SbtCommunityProject(
project = "betterfiles",
sbtTestCommand = "dotty-community-build/compile",
+ sbtDocCommand = ";core/doc ;akka/doc ;shapelessScanner/doc"
)
lazy val ScalaPB = SbtCommunityProject(
project = "ScalaPB",
sbtTestCommand = "dotty-community-build/compile",
+ // aggregateDoc("runtimeJVM")("scalapbc", "grpcRuntime", "compilerPlugin") fails with
+ // module class ScalaPbCodeGenerator$ has non-class parent: TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class )),module protocbridge),ProtocCodeGenerator)
+ // Also it seems that we do not handle correctly aggreagation projects
+ // sbtDocCommand = "dotty-community-build/doc"
+ sbtDocCommand = forceDoc("scalapbc", "grpcRuntime","runtimeJVM", "compilerPlugin")
)
lazy val minitest = SbtCommunityProject(
project = "minitest",
sbtTestCommand = "test",
+ sbtDocCommand = aggregateDoc("lawsJVM")("minitestJVM"),
dependencies = List(scalacheck)
)
lazy val fastparse = SbtCommunityProject(
project = "fastparse",
sbtTestCommand = "dotty-community-build/compile;dotty-community-build/test:compile",
+ // Problem parsing perftests/bench2/src/perftests/PythonParse.scala:[0..18..694]
+ // sbtDocCommand = "dotty-community-build/doc"
)
lazy val stdLib213 = SbtCommunityProject(
@@ -253,16 +305,20 @@ object projects:
extraSbtArgs = List("-Dscala.build.compileWithDotty=true"),
sbtTestCommand = """library/compile""",
sbtPublishCommand = """set publishArtifact in (library, Compile, packageDoc) := false ;library/publishLocal""",
+ // sbtDocCommand = "library/doc" // Does no compile? No idea :/
)
+
lazy val shapeless = SbtCommunityProject(
project = "shapeless",
sbtTestCommand = "test",
+ sbtDocCommand = forceDoc("typeable", "deriving", "data")
)
lazy val xmlInterpolator = SbtCommunityProject(
project = "xml-interpolator",
sbtTestCommand = "test",
+ sbtDocCommand = "doc", // Again we've got problem with extensions
)
lazy val effpi = SbtCommunityProject(
@@ -278,6 +334,7 @@ object projects:
// sbtTestCommand = "set ThisBuild / useEffpiPlugin := false; effpi/test:compile; plugin/test:compile; benchmarks/test:compile; examples/test:compile; pluginBenchmarks/test:compile",
sbtTestCommand = "set ThisBuild / useEffpiPlugin := false; effpi/test:compile; benchmarks/test:compile; examples/test:compile; pluginBenchmarks/test:compile",
+ sbtDocCommand = "set ThisBuild / useEffpiPlugin := false; effpi/doc; benchmarks/doc; examples/doc; pluginBenchmarks/doc",
)
// TODO @odersky? It got broken by #5458
@@ -289,11 +346,16 @@ object projects:
lazy val sconfig = SbtCommunityProject(
project = "sconfig",
sbtTestCommand = "sconfigJVM/test",
+ // sbtDocCommand = "sconfigJVM/doc", // Fails with:
+ // Problem parsing sconfig/sharedScala3/src/main/scala/org/ekrich/config/ConfigSyntax.scala:[73..92..1340], documentation may not be generated.
+ // scala.MatchError: ValDef(JSON,TypeTree[TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class ekrich)),module config),class ConfigSyntax)],Apply(Ident($new),List(Literal(Constant(0)), Literal(Constant(JSON))))) (of class dotty.tools.dotc.ast.Trees$ValDef)
)
lazy val zio = SbtCommunityProject(
project = "zio",
sbtTestCommand = "testJVMDotty",
+ // sbtDocCommand = forceDoc("coreJVM"),
+ // Fails on tasty unpickling https://github.com/lampepfl/dotty/issues/10499
)
lazy val munit = SbtCommunityProject(
@@ -301,6 +363,7 @@ object projects:
sbtTestCommand = "testsJVM/test;testsJS/test;",
// Hardcode the version to avoid having to deal with something set by sbt-dynver
sbtPublishCommand = s"""set every version := "${Versions.munit}"; munitJVM/publishLocal; munitJS/publishLocal; munitScalacheckJVM/publishLocal; munitScalacheckJS/publishLocal; junit/publishLocal""",
+ sbtDocCommand = "munitJVM/doc",
dependencies = List(scalacheck)
)
@@ -309,50 +372,76 @@ object projects:
sbtTestCommand = "coreJVM/test;coreJS/test",
// Hardcode the version to avoid having to deal with something set by sbt-git
sbtPublishCommand = s"""set every version := "${Versions.scodecBits}"; coreJVM/publishLocal;coreJS/publishLocal""",
+ sbtDocCommand = "coreJVM/doc",
dependencies = List(munit)
)
lazy val scodec = SbtCommunityProject(
project = "scodec",
sbtTestCommand = "unitTests/test",
+ // Adds package
+ sbtDocCommand = "coreJVM/doc",
dependencies = List(munit, scodecBits)
)
lazy val scalaParserCombinators = SbtCommunityProject(
project = "scala-parser-combinators",
sbtTestCommand = "parserCombinatorsJVM/test",
+ sbtDocCommand = forceDoc("parserCombinatorsJVM"),
)
lazy val dottyCpsAsync = SbtCommunityProject(
project = "dotty-cps-async",
sbtTestCommand = "test",
+ // Does not compile (before reaches doc)
+ // sbtDocCommand = "cpsJVM/doc",
)
lazy val scalaz = SbtCommunityProject(
project = "scalaz",
sbtTestCommand = "rootJVM/test",
+
+ // sbtDocCommand = forceDoc("coreJVM"), // Fails with:
+ // [error] class scalaz.Conts cannot be unpickled because no class file was found
+ // [error] class scalaz.ContsT cannot be unpickled because no class file was found
+ // [error] class scalaz.IndexedCont cannot be unpickled because no class file was found
+
+ // aggregateDoc("rootJVM")("effectJVM", "iterateeJVM"), // Fails With
+ // [error] Caused by: java.lang.AssertionError: assertion failed:
+ // trait MonadIO has non-class parent: AppliedType(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class )),module scalaz),Monad),List(TypeRef(ThisType(TypeRef(TermRef(ThisType(TypeRef(NoPrefix,module class scalaz)),module effect),trait MonadIO)),type F)))
+
+ // sbtDocCommand = forceDoc("iterateeJVM"), // Fails with
+ // [error] class scalaz.iteratee.Iteratee cannot be unpickled because no class file was found
+
+ sbtDocCommand = forceDoc("effectJVM"),
dependencies = List(scalacheck)
)
lazy val endpoints4s = SbtCommunityProject(
project = "endpoints4s",
- sbtTestCommand = "json-schemaJVM/compile;algebraJVM/compile;openapiJVM/compile;http4s-server/compile;http4s-client/compile;play-server/compile;play-client/compile;akka-http-server/compile;akka-http-client/compile"
+ sbtTestCommand = "json-schemaJVM/compile;algebraJVM/compile;openapiJVM/compile;http4s-server/compile;http4s-client/compile;play-server/compile;play-client/compile;akka-http-server/compile;akka-http-client/compile",
+ sbtDocCommand = ";json-schemaJVM/doc ;algebraJVM/doc; openapiJVM/doc; http4s-server/doc ;http4s-client/doc ;play-server/doc ;play-client/doc ;akka-http-server/doc ;akka-http-client/doc",
)
lazy val catsEffect2 = SbtCommunityProject(
project = "cats-effect-2",
- sbtTestCommand = "test"
+ sbtTestCommand = "test",
+ // Currently is excluded from community build
+ // sbtDocCommand = ";coreJVM/doc ;lawsJVM/doc",
)
lazy val catsEffect3 = SbtCommunityProject(
project = "cats-effect-3",
- sbtTestCommand = "testIfRelevant"
+ sbtTestCommand = "testIfRelevant",
+ // The problem is that testIfRelevant does not compile and project does not compile
+ // sbtDocCommand = ";coreJVM/doc ;lawsJVM/doc ;kernelJVM/doc",
)
lazy val scalaParallelCollections = SbtCommunityProject(
project = "scala-parallel-collections",
sbtTestCommand = "test",
- dependencies = List(scalacheck)
+ sbtDocCommand = forceDoc("core"),
+ dependencies = List(scalacheck)
)
lazy val scalaCollectionCompat = SbtCommunityProject(
@@ -363,6 +452,11 @@ object projects:
lazy val verify = SbtCommunityProject(
project = "verify",
sbtTestCommand = "verifyJVM/test",
+ sbtDocCommand = "verifyJVM/doc",
)
end projects
+
+def allProjects = projects.fields.of[CommunityProject].sortBy(_.project)
+
+lazy val projectMap = allProjects.map(p => p.project -> p).toMap
diff --git a/project/Build.scala b/project/Build.scala
index f5de6714f93e..9666386b2100 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -1335,6 +1335,8 @@ object Build {
(publishLocal in `tasty-core-bootstrapped`).value
(publishLocal in `scala3-library-bootstrapped`).value
(publishLocal in `scala3-doc-bootstrapped`).value
+ (publishLocal in `scala3-tasty-inspector`).value
+ (publishLocal in `scala3doc`).value
(publishLocal in `scala3-compiler-bootstrapped`).value
(publishLocal in `sbt-dotty`).value
(publishLocal in `scala3-bootstrapped`).value
@@ -1351,6 +1353,7 @@ object Build {
TestFrameworks.JUnit,
"--include-categories=dotty.communitybuild.TestCategory",
),
+ Compile/run := (Compile/run).dependsOn(prepareCommunityBuild).evaluated,
(Test / testOnly) := ((Test / testOnly) dependsOn prepareCommunityBuild).evaluated,
(Test / test ) := ((Test / test ) dependsOn prepareCommunityBuild).value,
javaOptions ++= {
@@ -1592,9 +1595,12 @@ object Build {
Build.testcasesSourceRoot.in(Test),
Build.testDocumentationRoot,
),
+ Compile / buildInfoKeys := Seq[BuildInfoKey](version),
+ Compile / buildInfoPackage := "dotty.dokka",
testDocumentationRoot := (baseDirectory.value / "test-documentations").getAbsolutePath,
- buildInfoPackage in Test := "dotty.dokka",
+ buildInfoPackage in Test := "dotty.dokka.test",
BuildInfoPlugin.buildInfoScopedSettings(Test),
+ BuildInfoPlugin.buildInfoScopedSettings(Compile),
BuildInfoPlugin.buildInfoDefaultSettings,
// Uncomment to debug dokka processing (require to run debug in listen mode on 5005 port)
// javaOptions.in(run) += "-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5005,suspend=y"
diff --git a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala
index 16e8e71f8aaa..ea87b5473028 100644
--- a/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala
+++ b/sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala
@@ -434,10 +434,12 @@ object DottyPlugin extends AutoPlugin {
private val docSettings = inTask(doc)(Seq(
tastyFiles := {
val _ = compile.value // Ensure that everything is compiled, so TASTy is available.
- (classDirectory.value ** "*.tasty").get.map(_.getAbsoluteFile)
+ // sbt is too smart and do not start doc task if there are no *.scala files defined
+ file("___fake___.scala") +:
+ (classDirectory.value ** "*.tasty").get.map(_.getAbsoluteFile)
},
sources := Def.taskDyn[Seq[File]] {
- if (isDotty.value) Def.task { tastyFiles.value }
+ if (isDotty.value && useScala3doc.value) Def.task { tastyFiles.value }
else Def.task { sources.value }
}.value,
scalacOptions ++= {
diff --git a/scala3doc/src/dotty/dokka/Scala3docArgs.scala b/scala3doc/src/dotty/dokka/Scala3docArgs.scala
index 0951e845ac4f..6c53329a9f92 100644
--- a/scala3doc/src/dotty/dokka/Scala3docArgs.scala
+++ b/scala3doc/src/dotty/dokka/Scala3docArgs.scala
@@ -69,8 +69,8 @@ object Scala3docArgs:
def parseTastyRoots(roots: String) =
roots.split(File.pathSeparatorChar).toList.map(new File(_))
- val (existing, nonExisting) =
- summary.arguments.map(File(_)).partition(_.exists)
+ val inFiles = summary.arguments.map(File(_)).filter(_.getName != "___fake___.scala")
+ val (existing, nonExisting) = inFiles.partition(_.exists)
if nonExisting.nonEmpty then report.warning(
s"Scala3doc will ignore following nonexisiten paths: ${nonExisting.mkString(", ")}"
diff --git a/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala b/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala
index 604f27c5f0dc..ed9db8933c10 100644
--- a/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala
+++ b/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala
@@ -12,16 +12,24 @@ class ScalaResourceInstaller(using ctx: DocContext) extends PageTransformer:
new RendererSpecificResourcePage(resourceName, java.util.ArrayList(), RenderingStrategy$Copy(s"/dotty_res/$resourceName"))
override def invoke(input: RootPageNode): RootPageNode =
- val defaultResources = input.getChildren.asScala ++ Seq("fonts", "images", "styles", "scripts", "hljs", "favicon.ico").map(dottyRes)
- val newResources = projectLogo ++ defaultResources ++ Seq(dynamicJsData)
+ val dirs = Seq("fonts", "images", "styles", "scripts", "hljs", "favicon.ico")
+ val defaultResources = input.getChildren.asScala ++ dirs.map(dottyRes)
+ val newResources =
+ projectLogo ++ defaultResources ++ Seq(dynamicJsData, scala3docVersionFile)
input.modified(input.getName, newResources.asJava)
+ private def textFile(path: String, content: String) =
+ val strategy = RenderingStrategy$Write(content)
+ new RendererSpecificResourcePage(path, java.util.ArrayList(), strategy)
+
private def dynamicJsData =
- // If data at any point will become more complex we should use a proper
- val data: Map[String, Map[String, String]] = Map("filterDefaults" -> FilterAttributes.defaultValues)
+ // If data at any point will become more complex we should use a proper mapping
+ val data: Map[String, Map[String, String]] =
+ Map("filterDefaults" -> FilterAttributes.defaultValues)
val str = new ObjectMapper().writeValueAsString(data.transform((_, v) => v.asJava).asJava)
+ textFile("scripts/data.js", s"var scala3DocData = $str")
- new RendererSpecificResourcePage("scripts/data.js", java.util.ArrayList(), RenderingStrategy$Write(s"var scala3DocData = $str"))
+ private def scala3docVersionFile = textFile("scala3doc.version", BuildInfo.version)
private def projectLogo = ctx.args.projectLogo.toSeq.map { path =>
val fileName = Paths.get(path).getFileName()
diff --git a/scala3doc/test/dotty/dokka/SignatureTest.scala b/scala3doc/test/dotty/dokka/SignatureTest.scala
index 9b2df12091ae..ec6f49c85dd4 100644
--- a/scala3doc/test/dotty/dokka/SignatureTest.scala
+++ b/scala3doc/test/dotty/dokka/SignatureTest.scala
@@ -3,6 +3,7 @@ package dotty.dokka
import scala.io.Source
import scala.jdk.CollectionConverters._
import scala.util.matching.Regex
+import dotty.dokka.test.BuildInfo
import org.jetbrains.dokka.pages.{RootPageNode, PageNode, ContentPage, ContentText, ContentNode, ContentComposite}
diff --git a/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala b/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala
index 8b6a5ca99a92..9180fd2f7bdf 100644
--- a/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala
+++ b/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala
@@ -9,6 +9,7 @@ import org.junit.Assert._
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.nio.charset.Charset
+import dotty.dokka.test.BuildInfo
class SiteGeneratationTest:
val projectName = "Test Project Name"
diff --git a/scala3doc/test/dotty/dokka/tasty/util/TestUtils.scala b/scala3doc/test/dotty/dokka/tasty/util/TestUtils.scala
index 055cfe6f5003..3a1cec87d723 100644
--- a/scala3doc/test/dotty/dokka/tasty/util/TestUtils.scala
+++ b/scala3doc/test/dotty/dokka/tasty/util/TestUtils.scala
@@ -1,6 +1,6 @@
package dotty.dokka.tasty.util
-import dotty.dokka.BuildInfo
+import dotty.dokka.test.BuildInfo
object TestUtils {
def listOurClasses(): List[String] = {
diff --git a/scala3doc/test/dotty/dokka/testUtils.scala b/scala3doc/test/dotty/dokka/testUtils.scala
index a5972edcad2d..54dcb1d6de4b 100644
--- a/scala3doc/test/dotty/dokka/testUtils.scala
+++ b/scala3doc/test/dotty/dokka/testUtils.scala
@@ -4,9 +4,11 @@ import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.reporting.Diagnostic
import dotty.tools.dotc.reporting.ConsoleReporter
import dotty.tools.dotc.interfaces.Diagnostic.{ERROR, INFO, WARNING}
+import dotty.dokka.test.BuildInfo
import org.junit.Assert._
import java.io.File
+
case class ReportedDiagnostics(errors: List[Diagnostic], warnings: List[Diagnostic], infos: List[Diagnostic]):
def errorMsgs = errors.map(_.msg.rawMessage)
def warningMsgs = warnings.map(_.msg.rawMessage)