@@ -2,6 +2,7 @@ import java.io.File
22import java .nio .file ._
33
44import Modes ._
5+ import ScaladocGeneration ._
56import com .jsuereth .sbtpgp .PgpKeys
67import sbt .Keys ._
78import sbt ._
@@ -59,6 +60,8 @@ object DottyJSPlugin extends AutoPlugin {
5960}
6061
6162object Build {
63+ import ScaladocConfigs ._
64+
6265 val referenceVersion = " 3.1.2-RC1"
6366
6467 val baseVersion = " 3.1.3-RC1"
@@ -1253,6 +1256,8 @@ object Build {
12531256 val generateScalaDocumentation = inputKey[Unit ](" Generate documentation for dotty lib" )
12541257 val generateTestcasesDocumentation = taskKey[Unit ](" Generate documentation for testcases, usefull for debugging tests" )
12551258
1259+ val generateReferenceDocumentation = taskKey[Unit ](" Generate language reference documentation for Scala 3" )
1260+
12561261 lazy val `scaladoc-testcases` = project.in(file(" scaladoc-testcases" )).
12571262 dependsOn(`scala3-compiler-bootstrapped`).
12581263 settings(commonBootstrappedSettings)
@@ -1287,39 +1292,15 @@ object Build {
12871292 libraryDependencies += (" org.scala-js" %%% " scalajs-dom" % " 1.1.0" ).cross(CrossVersion .for3Use2_13)
12881293 )
12891294
1290- def generateDocumentation (targets : Seq [ String ], name : String , outDir : String , ref : String , params : Seq [ String ] = Nil , includeExternalMappings : Boolean = true ) =
1295+ def generateDocumentation (configTask : Def . Initialize [ Task [ GenerationConfig ]] ) =
12911296 Def .taskDyn {
1292- val distLocation = (dist / pack).value
1293- val projectVersion = version.value
1294- IO .createDirectory(file(outDir))
1295- val stdLibVersion = stdlibVersion(NonBootstrapped )
1296- val scalaLib = findArtifactPath(externalCompilerClasspathTask.value, " scala-library" )
1297- val dottyLib = (`scala3-library` / Compile / classDirectory).value
1298- // TODO add versions etc.
1299- def srcManaged (v : String , s : String ) = s " out/bootstrap/stdlib-bootstrapped/scala- $v/src_managed/main/ $s-library-src "
1300- def scalaSrcLink (v : String , s : String ) = s " -source-links: ${s}github://scala/scala/v $v#src/library "
1301- def dottySrcLink (v : String , sourcesPrefix : String = " " , outputPrefix : String = " " ) =
1302- sys.env.get(" GITHUB_SHA" ) match {
1303- case Some (sha) =>
1304- s " -source-links: ${sourcesPrefix}github:// ${sys.env(" GITHUB_REPOSITORY" )}/ $sha$outputPrefix"
1305- case None => s " -source-links: ${sourcesPrefix}github://lampepfl/dotty/ $v$outputPrefix"
1306- }
1307-
1308- val revision = Seq (" -revision" , ref, " -project-version" , projectVersion)
1309- val cmd = Seq (
1310- " -d" ,
1311- outDir,
1312- " -project" ,
1313- name,
1314- scalaSrcLink(stdLibVersion, srcManaged(dottyNonBootstrappedVersion, " scala" ) + " =" ),
1315- dottySrcLink(referenceVersion, srcManaged(dottyNonBootstrappedVersion, " dotty" ) + " =" , " #library/src" ),
1316- dottySrcLink(referenceVersion),
1317- " -Ygenerate-inkuire" ,
1318- ) ++ scalacOptionsDocSettings(includeExternalMappings) ++ revision ++ params ++ targets
1319- import _root_ .scala .sys .process ._
1320- val escapedCmd = cmd.map(arg => if (arg.contains(" " )) s """ " $arg" """ else arg)
1297+ val config = configTask.value
1298+ config.get[OutputDir ].foreach { outDir =>
1299+ IO .createDirectory(file(outDir.value))
1300+ }
1301+ val command = generateCommand(config)
13211302 Def .task {
1322- (Compile / run).toTask(escapedCmd.mkString( " " , " " , " " ) ).value
1303+ (Compile / run).toTask(command ).value
13231304 }
13241305 }
13251306
@@ -1363,66 +1344,65 @@ object Build {
13631344 Test / testcasesSourceRoot := ((`scaladoc-testcases` / baseDirectory).value / " src" ).getAbsolutePath.toString,
13641345 run / baseDirectory := (ThisBuild / baseDirectory).value,
13651346 generateSelfDocumentation := Def .taskDyn {
1366- generateDocumentation(
1367- (Compile / classDirectory).value.getAbsolutePath :: Nil ,
1368- " scaladoc" , " scaladoc/output/self" , VersionUtil .gitHash, Seq (" -usejavacp" )
1369- )
1347+ generateDocumentation(Scaladoc )
13701348 }.value,
1349+
13711350 generateScalaDocumentation := Def .inputTaskDyn {
1372- val extraArgs = spaceDelimited(" [output]" ).parsed
1373- val dest = file(extraArgs.headOption.getOrElse(" scaladoc/output/scala3" )).getAbsoluteFile
1374- val justAPI = extraArgs.drop(1 ).headOption == Some (" --justAPI" )
13751351 val majorVersion = (LocalProject (" scala3-library-bootstrapped" ) / scalaBinaryVersion).value
1376- val dottyJars : Seq [java.io.File ] = Seq (
1377- (`stdlib-bootstrapped`/ Compile / products).value,
1378- (`scala3-interfaces`/ Compile / products).value,
1379- (`tasty-core-bootstrapped`/ Compile / products).value,
1380- ).flatten
1381-
1382- val roots = dottyJars.map(_.getAbsolutePath)
1383-
1384- val managedSources =
1385- (`stdlib-bootstrapped`/ Compile / sourceManaged).value / " scala-library-src"
1386- val projectRoot = (ThisBuild / baseDirectory).value.toPath
1387- val stdLibRoot = projectRoot.relativize(managedSources.toPath.normalize())
1388- val docRootFile = stdLibRoot.resolve(" rootdoc.txt" )
1389-
1390- val dottyManagesSources =
1391- (`stdlib-bootstrapped`/ Compile / sourceManaged).value / " dotty-library-src"
1392-
1393- val dottyLibRoot = projectRoot.relativize(dottyManagesSources.toPath.normalize())
1394-
1395- def generateDocTask =
1396- generateDocumentation(
1397- roots, " Scala 3" , dest.getAbsolutePath, " main" ,
1398- Seq (
1399- " -comment-syntax" , " wiki" ,
1400- s " -source-links:docs=github://lampepfl/dotty/main#docs " ,
1401- " -doc-root-content" , docRootFile.toString,
1402- " -versions-dictionary-url" ,
1403- " https://scala-lang.org/api/versions.json" ,
1404- " -Ydocument-synthetic-types" ,
1405- s " -snippet-compiler: ${dottyLibRoot}/scala/quoted=compile, ${dottyLibRoot}/scala/compiletime=compile "
1406- ) ++ (if (justAPI) Nil else Seq (" -siteroot" , " docs" , " -Yapi-subdirectory" )), includeExternalMappings = false )
1407-
1408- if (dottyJars.isEmpty) Def .task { streams.value.log.error(" Dotty lib wasn't found" ) }
1409- else if (justAPI) generateDocTask
1410- else Def .task{
1411- IO .write(dest / " versions" / " latest-nightly-base" , majorVersion)
1412-
1413- // This file is used by GitHub Pages when the page is available in a custom domain
1414- IO .write(dest / " CNAME" , " dotty.epfl.ch" )
1415- }.dependsOn(generateDocTask)
1352+
1353+ val extraArgs = spaceDelimited(" [<output-dir>] [--justAPI]" ).parsed
1354+ val outputDirOverride = extraArgs.headOption.fold(identity[GenerationConfig ](_))(newDir => {
1355+ config : GenerationConfig => config.add(OutputDir (newDir))
1356+ })
1357+ val justAPIArg : Option [String ] = extraArgs.drop(1 ).find(_ == " --justAPI" )
1358+ val justAPI = justAPIArg.fold(identity[GenerationConfig ](_))(_ => {
1359+ config : GenerationConfig => config.remove[SiteRoot ]
1360+ })
1361+ val overrideFunc = outputDirOverride.andThen(justAPI)
1362+
1363+ val config = Def .task {
1364+ overrideFunc(Scala3 .value)
1365+ }
1366+
1367+ val writeAdditionalFiles = Def .task {
1368+ val dest = file(config.value.get[OutputDir ].get.value)
1369+ if (justAPIArg.isEmpty) {
1370+ IO .write(dest / " versions" / " latest-nightly-base" , majorVersion)
1371+ // This file is used by GitHub Pages when the page is available in a custom domain
1372+ IO .write(dest / " CNAME" , " dotty.epfl.ch" )
1373+ }
1374+ }
1375+
1376+ writeAdditionalFiles.dependsOn(generateDocumentation(config))
14161377 }.evaluated,
14171378
14181379 generateTestcasesDocumentation := Def .taskDyn {
1419- generateDocumentation(
1420- (Test / Build .testcasesOutputDir).value,
1421- " scaladoc testcases" ,
1422- " scaladoc/output/testcases" ,
1423- " main" ,
1424- Seq (" -usejavacp" , " -snippet-compiler:scaladoc-testcases/docs=compile" , " -siteroot" , " scaladoc-testcases/docs" )
1380+ generateDocumentation(Testcases )
1381+ }.value,
1382+
1383+ generateReferenceDocumentation := Def .taskDyn {
1384+ val temp = IO .createTemporaryDirectory
1385+ IO .copyDirectory(file(" docs" ), temp / " docs" )
1386+ IO .delete(temp / " docs" / " _blog" )
1387+
1388+ IO .copyDirectory(
1389+ file(" project" ) / " resources" / " referenceReplacements" ,
1390+ temp / " docs" ,
1391+ overwrite = true
14251392 )
1393+
1394+ val languageReferenceConfig = Def .task {
1395+ Scala3 .value
1396+ .add(OutputDir (" scaladoc/output/reference" ))
1397+ .add(SiteRoot (s " ${temp.getAbsolutePath}/docs " ))
1398+ .add(ProjectName (" Scala 3 Reference" ))
1399+ .add(SourceLinks (List (
1400+ dottySrcLink(referenceVersion, temp.getAbsolutePath + " =" )
1401+ )))
1402+ .withTargets(List (" ___fake___.scala" ))
1403+ }
1404+
1405+ generateDocumentation(languageReferenceConfig)
14261406 }.value,
14271407
14281408 Test / buildInfoKeys := Seq [BuildInfoKey ](
@@ -1803,3 +1783,123 @@ object Build {
18031783 })
18041784 }
18051785}
1786+
1787+ object ScaladocConfigs {
1788+ import Build ._
1789+ private lazy val currentYear : String = java.util.Calendar .getInstance().get(java.util.Calendar .YEAR ).toString
1790+
1791+ def dottyExternalMapping = " .*scala/.*::scaladoc3::https://dotty.epfl.ch/api/"
1792+ def javaExternalMapping = " .*java/.*::javadoc::https://docs.oracle.com/javase/8/docs/api/"
1793+ def scalaSrcLink (v : String , s : String ) = s " ${s}github://scala/scala/v $v#src/library "
1794+ def dottySrcLink (v : String , sourcesPrefix : String = " " , outputPrefix : String = " " ) =
1795+ sys.env.get(" GITHUB_SHA" ) match {
1796+ case Some (sha) =>
1797+ s " ${sourcesPrefix}github:// ${sys.env(" GITHUB_REPOSITORY" )}/ $sha$outputPrefix"
1798+ case None => s " ${sourcesPrefix}github://lampepfl/dotty/ $v$outputPrefix"
1799+ }
1800+
1801+ lazy val DefaultGenerationConfig = Def .task {
1802+ def distLocation = (dist / pack).value
1803+ def projectVersion = version.value
1804+ def stdLibVersion = stdlibVersion(NonBootstrapped )
1805+ def scalaLib = findArtifactPath(externalCompilerClasspathTask.value, " scala-library" )
1806+ def dottyLib = (`scala3-library` / Compile / classDirectory).value
1807+ def srcManaged (v : String , s : String ) = s " out/bootstrap/stdlib-bootstrapped/scala- $v/src_managed/main/ $s-library-src "
1808+
1809+ def defaultSourceLinks : SourceLinks = SourceLinks (
1810+ List (
1811+ scalaSrcLink(stdLibVersion, srcManaged(dottyNonBootstrappedVersion, " scala" ) + " =" ),
1812+ dottySrcLink(referenceVersion, srcManaged(dottyNonBootstrappedVersion, " dotty" ) + " =" , " #library/src" ),
1813+ dottySrcLink(referenceVersion),
1814+ " docs=github://lampepfl/dotty/main#docs"
1815+ )
1816+ )
1817+ def socialLinks = SocialLinks (List (
1818+ " github::https://github.com/lampepfl/dotty" ,
1819+ " discord::https://discord.com/invite/scala" ,
1820+ " twitter::https://twitter.com/scala_lang" ,
1821+ ))
1822+ def projectLogo = ProjectLogo (" docs/_assets/images/logo.svg" )
1823+ def skipByRegex = SkipByRegex (List (" .+\\ .internal($|\\ ..+)" , " .+\\ .impl($|\\ ..+)" ))
1824+ def skipById = SkipById (List (
1825+ " scala.runtime.stdLibPatches" ,
1826+ " scala.runtime.MatchCase"
1827+ ))
1828+ def projectFooter = ProjectFooter (s " Copyright (c) 2002- $currentYear, LAMP/EPFL " )
1829+ def defaultTemplate = DefaultTemplate (" static-site-main" )
1830+ GenerationConfig (
1831+ List (),
1832+ ProjectVersion (projectVersion),
1833+ GenerateInkuire (true ),
1834+ defaultSourceLinks,
1835+ skipByRegex,
1836+ skipById,
1837+ projectLogo,
1838+ socialLinks,
1839+ projectFooter,
1840+ defaultTemplate,
1841+ Author (true ),
1842+ Groups (true )
1843+ )
1844+ }
1845+
1846+ lazy val Scaladoc = Def .task {
1847+ DefaultGenerationConfig .value
1848+ .add(UseJavacp (true ))
1849+ .add(ProjectName (" scaladoc" ))
1850+ .add(OutputDir (" scaladoc/output/self" ))
1851+ .add(Revision (VersionUtil .gitHash))
1852+ .add(ExternalMappings (List (dottyExternalMapping, javaExternalMapping)))
1853+ .withTargets((Compile / classDirectory).value.getAbsolutePath :: Nil )
1854+ }
1855+
1856+ lazy val Testcases = Def .task {
1857+ val tastyRoots = (Test / Build .testcasesOutputDir).value
1858+ DefaultGenerationConfig .value
1859+ .add(UseJavacp (true ))
1860+ .add(OutputDir (" scaladoc/output/testcases" ))
1861+ .add(ProjectName (" scaladoc testcases" ))
1862+ .add(Revision (" main" ))
1863+ .add(SnippetCompiler (List (" scaladoc-testcases/docs=compile" )))
1864+ .add(SiteRoot (" scaladoc-testcases/docs" ))
1865+ .add(ExternalMappings (List (dottyExternalMapping, javaExternalMapping)))
1866+ .withTargets(tastyRoots)
1867+ }
1868+
1869+ lazy val Scala3 = Def .task {
1870+ val dottyJars : Seq [java.io.File ] = Seq (
1871+ (`stdlib-bootstrapped`/ Compile / products).value,
1872+ (`scala3-interfaces`/ Compile / products).value,
1873+ (`tasty-core-bootstrapped`/ Compile / products).value,
1874+ ).flatten
1875+
1876+ val roots = dottyJars.map(_.getAbsolutePath)
1877+
1878+ val managedSources =
1879+ (`stdlib-bootstrapped`/ Compile / sourceManaged).value / " scala-library-src"
1880+ val projectRoot = (ThisBuild / baseDirectory).value.toPath
1881+ val stdLibRoot = projectRoot.relativize(managedSources.toPath.normalize())
1882+ val docRootFile = stdLibRoot.resolve(" rootdoc.txt" )
1883+
1884+ val dottyManagesSources =
1885+ (`stdlib-bootstrapped`/ Compile / sourceManaged).value / " dotty-library-src"
1886+
1887+ val dottyLibRoot = projectRoot.relativize(dottyManagesSources.toPath.normalize())
1888+ DefaultGenerationConfig .value
1889+ .add(ProjectName (" Scala 3" ))
1890+ .add(OutputDir (file(" scaladoc/output/scala3" ).getAbsoluteFile.getAbsolutePath))
1891+ .add(Revision (" main" ))
1892+ .add(ExternalMappings (List (javaExternalMapping)))
1893+ .add(DocRootContent (docRootFile.toString))
1894+ .add(CommentSyntax (" wiki" ))
1895+ .add(VersionsDictionaryUrl (" https://scala-lang.org/api/versions.json" ))
1896+ .add(DocumentSyntheticTypes (true ))
1897+ .add(SnippetCompiler (List (
1898+ s " ${dottyLibRoot}/scala/quoted=compile " ,
1899+ s " ${dottyLibRoot}/scala/compiletime=compile "
1900+ )))
1901+ .add(SiteRoot (" docs" ))
1902+ .add(ApiSubdirectory (true ))
1903+ .withTargets(roots)
1904+ }
1905+ }
0 commit comments