Skip to content

Commit ce02066

Browse files
committed
Add scaladoc to BuildInfo, make docs auto-generated
1 parent 05655ac commit ce02066

File tree

6 files changed

+245
-39
lines changed

6 files changed

+245
-39
lines changed

modules/build/src/test/scala/scala/build/tests/SourceGeneratorTests.scala

+20-18
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class SourceGeneratorTests extends munit.FunSuite {
3939
)
4040
)
4141

42-
private def normalizeResolvers(contents: String): String =
42+
private def normalizeContents(contents: String): String =
4343
contents
4444
.replaceAll(
4545
"ivy:file:[^\"]*scala-cli-tests-extra-repo[^\"]*/local-repo[^\"]*",
@@ -48,7 +48,9 @@ class SourceGeneratorTests extends munit.FunSuite {
4848
.replaceAll(
4949
"ivy:file:[^\"]*\\.ivy2/local[^\"]*",
5050
"ivy:file:.../.ivy2/local/"
51-
)
51+
).linesWithSeparators
52+
.filterNot(_.stripLeading().startsWith("/**"))
53+
.mkString
5254

5355
test(s"BuildInfo source generated") {
5456
val inputs = TestInputs(
@@ -85,7 +87,8 @@ class SourceGeneratorTests extends munit.FunSuite {
8587

8688
val buildInfoContent = os.read(buildInfoPath)
8789

88-
expect(normalizeResolvers(buildInfoContent) ==
90+
assertNoDiff(
91+
normalizeContents(buildInfoContent),
8992
s"""package scala.cli.build
9093
|
9194
|object BuildInfo {
@@ -97,7 +100,6 @@ class SourceGeneratorTests extends munit.FunSuite {
97100
| val scalaNativeVersion = None
98101
| val mainClass = Some("Main")
99102
|
100-
|
101103
| object Main {
102104
| val sources = Seq("${root / "main.scala"}")
103105
| val scalacOptions = Seq("-Xasync")
@@ -117,9 +119,9 @@ class SourceGeneratorTests extends munit.FunSuite {
117119
| val resourceDirs = Nil
118120
| val customJarsDecls = Nil
119121
| }
120-
|
121122
|}
122-
|""".stripMargin)
123+
|""".stripMargin
124+
)
123125
}
124126
}
125127

@@ -160,7 +162,8 @@ class SourceGeneratorTests extends munit.FunSuite {
160162

161163
val buildInfoContent = os.read(buildInfoPath)
162164

163-
expect(normalizeResolvers(buildInfoContent) ==
165+
assertNoDiff(
166+
normalizeContents(buildInfoContent),
164167
s"""package scala.cli.build
165168
|
166169
|object BuildInfo {
@@ -172,7 +175,6 @@ class SourceGeneratorTests extends munit.FunSuite {
172175
| val scalaNativeVersion = Some("0.4.6")
173176
| val mainClass = Some("Main")
174177
|
175-
|
176178
| object Main {
177179
| val sources = Seq("${root / "main.scala"}")
178180
| val scalacOptions = Seq("-Xasync")
@@ -192,9 +194,9 @@ class SourceGeneratorTests extends munit.FunSuite {
192194
| val resourceDirs = Nil
193195
| val customJarsDecls = Nil
194196
| }
195-
|
196197
|}
197-
|""".stripMargin)
198+
|""".stripMargin
199+
)
198200
}
199201
}
200202

@@ -236,7 +238,8 @@ class SourceGeneratorTests extends munit.FunSuite {
236238

237239
val buildInfoContent = os.read(buildInfoPath)
238240

239-
expect(normalizeResolvers(buildInfoContent) ==
241+
assertNoDiff(
242+
normalizeContents(buildInfoContent),
240243
s"""package scala.cli.build
241244
|
242245
|object BuildInfo {
@@ -248,7 +251,6 @@ class SourceGeneratorTests extends munit.FunSuite {
248251
| val scalaNativeVersion = None
249252
| val mainClass = Some("Main")
250253
|
251-
|
252254
| object Main {
253255
| val sources = Seq("${root / "main.scala"}")
254256
| val scalacOptions = Seq("-Xasync")
@@ -268,9 +270,9 @@ class SourceGeneratorTests extends munit.FunSuite {
268270
| val resourceDirs = Nil
269271
| val customJarsDecls = Nil
270272
| }
271-
|
272273
|}
273-
|""".stripMargin)
274+
|""".stripMargin
275+
)
274276
}
275277
}
276278

@@ -309,7 +311,8 @@ class SourceGeneratorTests extends munit.FunSuite {
309311

310312
val buildInfoContent = os.read(buildInfoPath)
311313

312-
expect(normalizeResolvers(buildInfoContent) ==
314+
assertNoDiff(
315+
normalizeContents(buildInfoContent),
313316
s"""package scala.cli.build
314317
|
315318
|object BuildInfo {
@@ -321,7 +324,6 @@ class SourceGeneratorTests extends munit.FunSuite {
321324
| val scalaNativeVersion = None
322325
| val mainClass = Some("Main")
323326
|
324-
|
325327
| object Main {
326328
| val sources = Seq("${root / "main.scala"}")
327329
| val scalacOptions = Seq("-Xasync")
@@ -341,9 +343,9 @@ class SourceGeneratorTests extends munit.FunSuite {
341343
| val resourceDirs = Nil
342344
| val customJarsDecls = Nil
343345
| }
344-
|
345346
|}
346-
|""".stripMargin)
347+
|""".stripMargin
348+
)
347349
}
348350
}
349351
}

modules/generate-reference-doc/src/main/scala/scala/cli/doc/GenerateReferenceDoc.scala

+89
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import shapeless.tag
1111
import java.nio.charset.StandardCharsets
1212
import java.util
1313

14+
import scala.build.info.{ArtifactId, BuildInfo, ExportDependencyFormat, ScopedBuildInfo}
1415
import scala.build.options.{BuildOptions, BuildRequirements, WithBuildRequirements}
1516
import scala.build.preprocessing.directives.DirectiveHandler
1617
import scala.build.preprocessing.directives.DirectivesPreprocessingUtils.*
@@ -481,6 +482,92 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] {
481482
b.toString
482483
}
483484

485+
private def buildInfoContent: String = {
486+
val b = new StringBuilder
487+
488+
b.section(
489+
"""---
490+
|title: BuildInfo
491+
|sidebar_position: 6
492+
|---""".stripMargin
493+
)
494+
b.section(
495+
""":::caution
496+
|BuildInfo is a restricted feature and requires setting the `--power` option to be used.
497+
|You can pass it explicitly or set it globally by running:
498+
|
499+
| scala-cli config power true
500+
|:::""".stripMargin
501+
)
502+
503+
b.section(
504+
"""During the building process Scala CLI collects information about the project's configuration,
505+
|both from the console options and `using directives` found in the project's sources.
506+
|You can access this information from your code using the `BuildInfo` object, that's automatically generated for your
507+
|build when requested.""".stripMargin
508+
)
509+
510+
b.section(
511+
"""To enable BuildInfo generation pass the `--build-info` option to Scala CLI or use a
512+
|`//> using buildInfo` directive.""".stripMargin
513+
)
514+
515+
b.section(
516+
"""## Usage
517+
|
518+
|To access the BuildInfo object you need to import it first. It is available in package `scala.cli.build` so use
519+
|```scala
520+
|import scala.cli.build.BuildInfo
521+
|```
522+
|to import it.
523+
|
524+
|Below you can find an example instance of the BuildInfo object, with all fields explained.
525+
|Some of the values have been shortened for readability.""".stripMargin
526+
)
527+
528+
val osLibDep = ExportDependencyFormat("com.lihaoyi", ArtifactId("os-lib", "os-lib_3"), "0.9.1")
529+
val toolkitDep =
530+
ExportDependencyFormat("org.scala-lang", ArtifactId("toolkit", "toolkit_3"), "latest.release")
531+
532+
val mainScopedBuildInfo = ScopedBuildInfo(BuildOptions(), Seq(".../Main.scala")).copy(
533+
scalacOptions = Seq("-Werror"),
534+
scalaCompilerPlugins = Nil,
535+
dependencies = Seq(osLibDep),
536+
resolvers = Seq("https://repo1.maven.org/maven2", "ivy:file:..."),
537+
resourceDirs = Seq(".../resources"),
538+
customJarsDecls = Seq(".../AwesomeJar1.jar", ".../AwesomeJar2.jar")
539+
)
540+
541+
val testScopedBuildInfo = ScopedBuildInfo(BuildOptions(), Seq(".../MyTests.scala")).copy(
542+
scalacOptions = Seq("-Vdebug"),
543+
scalaCompilerPlugins = Nil,
544+
dependencies = Seq(toolkitDep),
545+
resolvers = Seq("https://repo1.maven.org/maven2", "ivy:file:..."),
546+
resourceDirs = Seq(".../test/resources"),
547+
customJarsDecls = Nil
548+
)
549+
550+
val buildInfo = BuildInfo(BuildOptions()).copy(
551+
scalaVersion = Some("3.3.0"),
552+
platform = Some("JVM"),
553+
jvmVersion = Some("11"),
554+
scalaJsVersion = None,
555+
jsEsVersion = None,
556+
scalaNativeVersion = None,
557+
mainClass = Some("Main")
558+
)
559+
.withScope("main", mainScopedBuildInfo)
560+
.withScope("test", testScopedBuildInfo)
561+
562+
b.section(
563+
s"""```scala
564+
|${buildInfo.generateContents().strip()}
565+
|```""".stripMargin
566+
)
567+
568+
b.mkString
569+
}
570+
484571
def run(options: InternalDocOptions, args: RemainingArgs): Unit = {
485572

486573
val scalaCli = new ScalaCliCommands(
@@ -512,6 +599,7 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] {
512599
requireDirectiveHandlers,
513600
onlyRestricted = false
514601
)
602+
515603
val restrictedDirectivesContent = usingContent(
516604
allUsingDirectiveHandlers.filterNot(_.isRestricted),
517605
requireDirectiveHandlers.filterNot(_.isRestricted),
@@ -551,6 +639,7 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] {
551639
maybeWrite(options.outputPath / "cli-options.md", allCliOptionsContent)
552640
maybeWrite(options.outputPath / "commands.md", allCommandsContent)
553641
maybeWrite(options.outputPath / "directives.md", allDirectivesContent)
642+
maybeWrite(options.outputPath / "build-info.md", buildInfoContent)
554643

555644
maybeWrite(
556645
options.outputPath / restrictedDocsDir / "cli-options.md",

modules/options/src/main/scala/scala/build/info/BuildInfo.scala

+32-11
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,38 @@ final case class BuildInfo(
3131
val nl = System.lineSeparator()
3232
val indent = " " * 2
3333
val stringVals = Seq(
34+
"/** version of Scala used to compile this project */",
3435
s"val scalaVersion = \"${escapeBackslashes(scalaVersion.getOrElse(Constants.defaultScalaVersion))}\"",
36+
"/** target platform of this project, it can be \"JVM\" or \"JS\" or \"Native\" */",
3537
s"val platform = \"${escapeBackslashes(platform.getOrElse(Platform.JVM.repr))}\""
3638
)
3739

3840
val optionVals = Seq(
39-
"val jvmVersion =" -> jvmVersion,
40-
"val scalaJsVersion =" -> scalaJsVersion,
41-
"val jsEsVersion =" -> jsEsVersion,
42-
"val scalaNativeVersion =" -> scalaNativeVersion,
43-
"val mainClass =" -> mainClass
44-
).map { case (prefix, opt) =>
45-
opt.map(v => s"$prefix Some(\"${escapeBackslashes(v)}\")").getOrElse(s"$prefix None")
41+
Seq(
42+
"/** version of JVM, if it's the target platform */",
43+
"val jvmVersion ="
44+
) -> jvmVersion,
45+
Seq(
46+
"/** version of Scala.js, if it's the target platform */",
47+
"val scalaJsVersion ="
48+
) -> scalaJsVersion,
49+
Seq(
50+
"/** Scala.js ECMA Script version, if Scala.js is the target platform */",
51+
"val jsEsVersion ="
52+
) -> jsEsVersion,
53+
Seq(
54+
"/** version of Scala Native, if it's the target platform */",
55+
"val scalaNativeVersion ="
56+
) -> scalaNativeVersion,
57+
Seq(
58+
"/** Main class specified for the project */",
59+
"val mainClass ="
60+
) -> mainClass
61+
).flatMap { case (Seq(scaladoc, prefix), opt) =>
62+
Seq(
63+
scaladoc,
64+
opt.map(v => s"$prefix Some(\"${escapeBackslashes(v)}\")").getOrElse(s"$prefix None")
65+
)
4666
}
4767

4868
val allVals = stringVals ++ optionVals
@@ -52,17 +72,18 @@ final case class BuildInfo(
5272
yield {
5373
val scopedBuildInfoVals = scopedBuildInfo.generateContentLines()
5474
.mkString(indent, nl + indent * 2, "")
55-
s"""${indent}object ${scopeName.capitalize} {
75+
s"""$indent/** Information about the ${scopeName.capitalize} scope */
76+
|${indent}object ${scopeName.capitalize} {
5677
|$indent$scopedBuildInfoVals
57-
|$indent}
58-
|""".stripMargin
78+
|$indent}""".stripMargin
5979
}
6080

6181
s"""package scala.cli.build
6282
|
83+
|/** Information about the build gathered by Scala CLI */
6384
|object BuildInfo {
6485
|${allVals.mkString(indent, nl + indent, nl)}
65-
|${scopesContents.mkString(nl, nl, "")}
86+
|${scopesContents.mkString(nl * 2)}
6687
|}
6788
|""".stripMargin
6889
}

modules/options/src/main/scala/scala/build/info/ScopedBuildInfo.scala

+14-9
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,27 @@ final case class ScopedBuildInfo(
2525

2626
def generateContentLines(): Seq[String] =
2727
Seq(
28-
s"val sources = " -> sources,
29-
s"val scalacOptions = " -> scalacOptions,
30-
s"val scalaCompilerPlugins = " -> scalaCompilerPlugins.map(_.toString()),
31-
s"val dependencies = " -> dependencies.map(_.toString()),
32-
s"val resolvers = " -> resolvers,
33-
s"val resourceDirs = " -> resourceDirs,
34-
s"val customJarsDecls = " -> customJarsDecls
35-
).map { case (prefix, values) =>
28+
Seq("/** sources found for the scope */", "val sources = ") -> sources,
29+
Seq("/** scalac options for the scope */", "val scalacOptions = ") -> scalacOptions,
30+
Seq(
31+
"/** compiler plugins used in this scope */",
32+
"val scalaCompilerPlugins = "
33+
) -> scalaCompilerPlugins.map(_.toString()),
34+
Seq("/** dependencies used in this scope */", "val dependencies = ") -> dependencies.map(
35+
_.toString()
36+
),
37+
Seq("/** dependency resolvers used in this scope */", "val resolvers = ") -> resolvers,
38+
Seq("/** resource directories used in this scope */", "val resourceDirs = ") -> resourceDirs,
39+
Seq("/** custom jars added to this scope */", "val customJarsDecls = ") -> customJarsDecls
40+
).flatMap { case (Seq(scaladoc, prefix), values) =>
3641
val sb = new StringBuilder
3742
sb.append(prefix)
3843
if (values.isEmpty) sb.append("Nil")
3944
else sb.append {
4045
values.map(str => s"\"${BuildInfo.escapeBackslashes(str)}\"")
4146
.mkString("Seq(", ", ", ")")
4247
}
43-
sb.toString()
48+
Seq(scaladoc, sb.toString())
4449
}
4550
}
4651

website/docs/reference/bloop.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Interaction with Bloop server
3-
sidebar_position: 6
3+
sidebar_position: 10
44
---
55

66
# Interaction with Bloop server

0 commit comments

Comments
 (0)