Skip to content

Commit adc8ed4

Browse files
MaciejG604lwronski
andauthored
Document BuildInfo (#2325)
* Edit warning in password option section * Add scaladoc to BuildInfo, make docs auto-generated * Fix compilation error after merge * Update reference doc --------- Co-authored-by: Łukasz Wroński <[email protected]>
1 parent 0036400 commit adc8ed4

File tree

7 files changed

+263
-42
lines changed

7 files changed

+263
-42
lines changed

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

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class SourceGeneratorTests extends munit.FunSuite {
4040
)
4141
)
4242

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

5456
def initializeGit(
5557
cwd: os.Path,
@@ -111,7 +113,8 @@ class SourceGeneratorTests extends munit.FunSuite {
111113

112114
val buildInfoContent = os.read(buildInfoPath)
113115

114-
expect(normalizeResolvers(buildInfoContent) ==
116+
assertNoDiff(
117+
normalizeContents(buildInfoContent),
115118
s"""package scala.cli.build
116119
|
117120
|object BuildInfo {
@@ -124,7 +127,6 @@ class SourceGeneratorTests extends munit.FunSuite {
124127
| val mainClass = Some("Main")
125128
| val projectVersion = Some("1.0.0")
126129
|
127-
|
128130
| object Main {
129131
| val sources = Seq("${root / "main.scala"}")
130132
| val scalacOptions = Seq("-Xasync")
@@ -144,11 +146,11 @@ class SourceGeneratorTests extends munit.FunSuite {
144146
| val resourceDirs = Nil
145147
| val customJarsDecls = Nil
146148
| }
147-
|
148149
|}
149-
|""".stripMargin)
150-
}
150+
|""".stripMargin
151+
)
151152
}
153+
}
152154

153155
}
154156

@@ -189,7 +191,8 @@ class SourceGeneratorTests extends munit.FunSuite {
189191

190192
val buildInfoContent = os.read(buildInfoPath)
191193

192-
expect(normalizeResolvers(buildInfoContent) ==
194+
assertNoDiff(
195+
normalizeContents(buildInfoContent),
193196
s"""package scala.cli.build
194197
|
195198
|object BuildInfo {
@@ -202,7 +205,6 @@ class SourceGeneratorTests extends munit.FunSuite {
202205
| val mainClass = Some("Main")
203206
| val projectVersion = None
204207
|
205-
|
206208
| object Main {
207209
| val sources = Seq("${root / "main.scala"}")
208210
| val scalacOptions = Seq("-Xasync")
@@ -222,9 +224,9 @@ class SourceGeneratorTests extends munit.FunSuite {
222224
| val resourceDirs = Nil
223225
| val customJarsDecls = Nil
224226
| }
225-
|
226227
|}
227-
|""".stripMargin)
228+
|""".stripMargin
229+
)
228230
}
229231
}
230232

@@ -267,7 +269,8 @@ class SourceGeneratorTests extends munit.FunSuite {
267269

268270
val buildInfoContent = os.read(buildInfoPath)
269271

270-
expect(normalizeResolvers(buildInfoContent) ==
272+
assertNoDiff(
273+
normalizeContents(buildInfoContent),
271274
s"""package scala.cli.build
272275
|
273276
|object BuildInfo {
@@ -280,7 +283,6 @@ class SourceGeneratorTests extends munit.FunSuite {
280283
| val mainClass = Some("Main")
281284
| val projectVersion = Some("TestVersion")
282285
|
283-
|
284286
| object Main {
285287
| val sources = Seq("${root / "main.scala"}")
286288
| val scalacOptions = Seq("-Xasync")
@@ -300,9 +302,9 @@ class SourceGeneratorTests extends munit.FunSuite {
300302
| val resourceDirs = Nil
301303
| val customJarsDecls = Nil
302304
| }
303-
|
304305
|}
305-
|""".stripMargin)
306+
|""".stripMargin
307+
)
306308
}
307309
}
308310

@@ -342,7 +344,8 @@ class SourceGeneratorTests extends munit.FunSuite {
342344

343345
val buildInfoContent = os.read(buildInfoPath)
344346

345-
expect(normalizeResolvers(buildInfoContent) ==
347+
assertNoDiff(
348+
normalizeContents(buildInfoContent),
346349
s"""package scala.cli.build
347350
|
348351
|object BuildInfo {
@@ -355,7 +358,6 @@ class SourceGeneratorTests extends munit.FunSuite {
355358
| val mainClass = Some("Main")
356359
| val projectVersion = Some("TestVersion")
357360
|
358-
|
359361
| object Main {
360362
| val sources = Seq("${root / "main.scala"}")
361363
| val scalacOptions = Seq("-Xasync")
@@ -375,9 +377,9 @@ class SourceGeneratorTests extends munit.FunSuite {
375377
| val resourceDirs = Nil
376378
| val customJarsDecls = Nil
377379
| }
378-
|
379380
|}
380-
|""".stripMargin)
381+
|""".stripMargin
382+
)
381383
}
382384
}
383385
}

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

Lines changed: 98 additions & 0 deletions
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,100 @@ 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 on compile when that information changes.""".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+
|The generated BuildInfo object is available on the project's classpath. To access it you need to import it first.
519+
|It is available in the package `scala.cli.build` so use
520+
|```scala
521+
|import scala.cli.build.BuildInfo
522+
|```
523+
|to import it.
524+
|
525+
|Below you can find an example instance of the BuildInfo object, with all fields explained.
526+
|Some of the values have been shortened for readability.""".stripMargin
527+
)
528+
529+
val osLibDep = ExportDependencyFormat("com.lihaoyi", ArtifactId("os-lib", "os-lib_3"), "0.9.1")
530+
val toolkitDep =
531+
ExportDependencyFormat("org.scala-lang", ArtifactId("toolkit", "toolkit_3"), "latest.release")
532+
533+
val mainScopedBuildInfo = ScopedBuildInfo(BuildOptions(), Seq(".../Main.scala")).copy(
534+
scalacOptions = Seq("-Werror"),
535+
scalaCompilerPlugins = Nil,
536+
dependencies = Seq(osLibDep),
537+
resolvers = Seq("https://repo1.maven.org/maven2", "ivy:file:..."),
538+
resourceDirs = Seq(".../resources"),
539+
customJarsDecls = Seq(".../AwesomeJar1.jar", ".../AwesomeJar2.jar")
540+
)
541+
542+
val testScopedBuildInfo = ScopedBuildInfo(BuildOptions(), Seq(".../MyTests.scala")).copy(
543+
scalacOptions = Seq("-Vdebug"),
544+
scalaCompilerPlugins = Nil,
545+
dependencies = Seq(toolkitDep),
546+
resolvers = Seq("https://repo1.maven.org/maven2", "ivy:file:..."),
547+
resourceDirs = Seq(".../test/resources"),
548+
customJarsDecls = Nil
549+
)
550+
551+
val generatedBuildInfo = BuildInfo(BuildOptions(), os.pwd) match {
552+
case Right(bv) => bv
553+
case Left(exception) =>
554+
System.err.println(s"Failed to generate BuildInfo: ${exception.message}")
555+
sys.exit(1)
556+
}
557+
558+
val buildInfo = generatedBuildInfo.copy(
559+
scalaVersion = Some("3.3.0"),
560+
platform = Some("JVM"),
561+
jvmVersion = Some("11"),
562+
scalaJsVersion = None,
563+
jsEsVersion = None,
564+
scalaNativeVersion = None,
565+
mainClass = Some("Main")
566+
)
567+
.withScope("main", mainScopedBuildInfo)
568+
.withScope("test", testScopedBuildInfo)
569+
570+
b.section(
571+
s"""```scala
572+
|${buildInfo.generateContents().strip()}
573+
|```""".stripMargin
574+
)
575+
576+
b.mkString
577+
}
578+
484579
def run(options: InternalDocOptions, args: RemainingArgs): Unit = {
485580

486581
val scalaCli = new ScalaCliCommands(
@@ -512,6 +607,7 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] {
512607
requireDirectiveHandlers,
513608
onlyRestricted = false
514609
)
610+
515611
val restrictedDirectivesContent = usingContent(
516612
allUsingDirectiveHandlers.filterNot(_.isRestricted),
517613
requireDirectiveHandlers.filterNot(_.isRestricted),
@@ -524,6 +620,7 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] {
524620
(os.rel / "cli-options.md") -> allCliOptionsContent,
525621
(os.rel / "commands.md") -> allCommandsContent,
526622
(os.rel / "directives.md") -> allDirectivesContent,
623+
(os.rel / "build-info.md") -> buildInfoContent,
527624
(os.rel / restrictedDocsDir / "cli-options.md") -> restrictedCliOptionsContent,
528625
(os.rel / restrictedDocsDir / "commands.md") -> restrictedCommandsContent,
529626
(os.rel / restrictedDocsDir / "directives.md") -> restrictedDirectivesContent,
@@ -551,6 +648,7 @@ object GenerateReferenceDoc extends CaseApp[InternalDocOptions] {
551648
maybeWrite(options.outputPath / "cli-options.md", allCliOptionsContent)
552649
maybeWrite(options.outputPath / "commands.md", allCommandsContent)
553650
maybeWrite(options.outputPath / "directives.md", allDirectivesContent)
651+
maybeWrite(options.outputPath / "build-info.md", buildInfoContent)
554652

555653
maybeWrite(
556654
options.outputPath / restrictedDocsDir / "cli-options.md",

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

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,42 @@ final case class BuildInfo(
3434
val nl = System.lineSeparator()
3535
val indent = " " * 2
3636
val stringVals = Seq(
37+
"/** version of Scala used to compile this project */",
3738
s"val scalaVersion = \"${escapeBackslashes(scalaVersion.getOrElse(Constants.defaultScalaVersion))}\"",
39+
"/** target platform of this project, it can be \"JVM\" or \"JS\" or \"Native\" */",
3840
s"val platform = \"${escapeBackslashes(platform.getOrElse(Platform.JVM.repr))}\""
3941
)
4042

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

5275
val allVals = stringVals ++ optionVals
@@ -56,17 +79,18 @@ final case class BuildInfo(
5679
yield {
5780
val scopedBuildInfoVals = scopedBuildInfo.generateContentLines()
5881
.mkString(indent, nl + indent * 2, "")
59-
s"""${indent}object ${scopeName.capitalize} {
82+
s"""$indent/** Information about the ${scopeName.capitalize} scope */
83+
|${indent}object ${scopeName.capitalize} {
6084
|$indent$scopedBuildInfoVals
61-
|$indent}
62-
|""".stripMargin
85+
|$indent}""".stripMargin
6386
}
6487

6588
s"""package scala.cli.build
6689
|
90+
|/** Information about the build gathered by Scala CLI */
6791
|object BuildInfo {
6892
|${allVals.mkString(indent, nl + indent, nl)}
69-
|${scopesContents.mkString(nl, nl, "")}
93+
|${scopesContents.mkString(nl * 2)}
7094
|}
7195
|""".stripMargin
7296
}

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

Lines changed: 14 additions & 9 deletions
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

Lines changed: 1 addition & 1 deletion
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)