Skip to content

Commit a6c5516

Browse files
committed
Support .test.java inputs as test scope sources
1 parent 55227b0 commit a6c5516

8 files changed

Lines changed: 91 additions & 20 deletions

File tree

modules/build/src/main/scala/scala/build/CrossSources.scala

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ final case class CrossSources(
135135
}
136136

137137
object CrossSources {
138+
private val testScopeFileSuffixes: Set[String] = Set(".test.scala", ".test.java")
139+
140+
private def hasTestScopeSuffix(fileName: String): Boolean =
141+
testScopeFileSuffixes.exists(fileName.endsWith)
138142

139143
private def withinTestSubDirectory(p: ScopePath, inputs: Inputs): Boolean =
140144
p.root.exists { path =>
@@ -248,12 +252,14 @@ object CrossSources {
248252
.flatMap(_.valueFor(path).toSeq)
249253
.foldLeft(BuildRequirements())(_.orElse(_))
250254

251-
// Scala CLI treats all `.test.scala` files tests as well as
252-
// files from within `test` subdirectory from provided input directories
253-
// If file has `using target <scope>` directive this take precendeces.
255+
// Scala CLI treats all source files whose names end with one of the
256+
// testScopeFileSuffixes (e.g. `.test.scala`, `.test.java`) as tests, as well as
257+
// files from within `test` subdirectory from provided input directories.
258+
// If file has `using target <scope>` directive this takes precedence.
254259
if (
255260
fromDirectives.scope.isEmpty &&
256-
(path.subPath.last.endsWith(".test.scala") || withinTestSubDirectory(path, allInputs))
261+
(CrossSources.hasTestScopeSuffix(path.subPath.last) ||
262+
withinTestSubDirectory(path, allInputs))
257263
)
258264
fromDirectives.copy(scope = Some(BuildRequirements.ScopeRequirement(Scope.Test)))
259265
else fromDirectives

modules/build/src/main/scala/scala/build/preprocessing/JavaPreprocessor.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import scala.build.Logger
1010
import scala.build.errors.BuildException
1111
import scala.build.input.{JavaFile, ScalaCliInvokeData, SingleElement, VirtualJavaFile}
1212
import scala.build.internal.JavaParserProxyMaker
13-
import scala.build.options.{BuildRequirements, SuppressWarningOptions}
13+
import scala.build.options.SuppressWarningOptions
1414
import scala.build.preprocessing.directives.PreprocessedDirectives
1515

1616
/** Java source preprocessor.
@@ -56,8 +56,8 @@ final case class JavaPreprocessor(
5656
path = j.path,
5757
options = Some(preprocessedDirectives.globalUsings),
5858
optionsWithTargetRequirements = preprocessedDirectives.usingsWithReqs,
59-
requirements = Some(BuildRequirements()),
60-
scopedRequirements = Nil,
59+
requirements = Some(preprocessedDirectives.globalReqs),
60+
scopedRequirements = preprocessedDirectives.scopedReqs,
6161
mainClassOpt = None,
6262
directivesPositions = preprocessedDirectives.directivesPositions
6363
))
@@ -102,8 +102,8 @@ final case class JavaPreprocessor(
102102
wrapperParamsOpt = None,
103103
options = Some(preprocessedDirectives.globalUsings),
104104
optionsWithTargetRequirements = preprocessedDirectives.usingsWithReqs,
105-
requirements = Some(BuildRequirements()),
106-
scopedRequirements = Nil,
105+
requirements = Some(preprocessedDirectives.globalReqs),
106+
scopedRequirements = preprocessedDirectives.scopedReqs,
107107
mainClassOpt = None,
108108
scopePath = v.scopePath,
109109
directivesPositions = preprocessedDirectives.directivesPositions

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,71 @@ class SourcesTests extends TestUtil.ScalaCliBuildSuite {
334334
}
335335
}
336336

337+
/** Asserts that the only Java source produced by `testInputs` is routed to the test scope and
338+
* appears at `expectedPath`.
339+
*/
340+
private def expectJavaFileRoutedToTestScope(
341+
testInputs: TestInputs,
342+
expectedPath: os.RelPath
343+
): Unit =
344+
testInputs.withInputs { (root, inputs) =>
345+
val (crossSources, _) =
346+
CrossSources.forInputs(
347+
inputs,
348+
preprocessors,
349+
TestLogger(),
350+
SuppressWarningOptions()
351+
).orThrow
352+
353+
val scopedSources = crossSources.scopedSources(BuildOptions()).orThrow
354+
val mainSources =
355+
scopedSources.sources(
356+
Scope.Main,
357+
crossSources.sharedOptions(BuildOptions()),
358+
root,
359+
TestLogger()
360+
).orThrow
361+
val testSources =
362+
scopedSources.sources(
363+
Scope.Test,
364+
crossSources.sharedOptions(BuildOptions()),
365+
root,
366+
TestLogger()
367+
).orThrow
368+
369+
expect(mainSources.paths.isEmpty)
370+
expect(testSources.paths.map(_._2) == Seq(expectedPath))
371+
}
372+
373+
private val javaTestSourceContent: String =
374+
"""public class Something {
375+
| public int a = 1;
376+
|}
377+
|""".stripMargin
378+
379+
test("a .test.java file should be routed to the test scope") {
380+
val expectedPath = os.rel / "Something.test.java"
381+
val testInputs = TestInputs(expectedPath -> javaTestSourceContent)
382+
expectJavaFileRoutedToTestScope(testInputs, expectedPath)
383+
}
384+
385+
test("a .java file under a test/ directory should be routed to the test scope") {
386+
val expectedPath = os.rel / "test" / "Something.java"
387+
val testInputs = TestInputs(Seq(expectedPath -> javaTestSourceContent), Seq("."))
388+
expectJavaFileRoutedToTestScope(testInputs, expectedPath)
389+
}
390+
391+
test("a .java file with //> using target.scope test should be routed to the test scope") {
392+
val expectedPath = os.rel / "Something.java"
393+
val testInputs = TestInputs(
394+
expectedPath ->
395+
s"""//> using target.scope test
396+
|
397+
|$javaTestSourceContent""".stripMargin
398+
)
399+
expectJavaFileRoutedToTestScope(testInputs, expectedPath)
400+
}
401+
337402
test("should skip SheBang in .sc and .scala") {
338403
val testInputs = TestInputs(
339404
os.rel / "something1.sc" ->

modules/cli/src/main/scala/scala/cli/commands/test/TestOptions.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ object TestOptions {
4343
implicit lazy val help: Help[TestOptions] = Help.derive
4444

4545
val cmdName = "test"
46-
private val helpHeader = "Compile and test Scala code."
46+
private val helpHeader = "Compile and test Scala (or Java) code."
4747
val helpMessage: String = HelpMessages.shortHelpMessage(cmdName, helpHeader)
4848
val detailedHelpMessage: String =
4949
s"""$helpHeader
5050
|
5151
|Test sources are compiled separately (after the 'main' sources), and may use different dependencies, compiler options, and other configurations.
5252
|A source file is treated as a test source if:
53-
| - the file name ends with `.test.scala`
53+
| - the file name ends with `.test.scala` or `.test.java`
5454
| - the file comes from a directory that is provided as input, and the relative path from that file to its original directory contains a `test` directory
5555
| - it contains the `//> using target.scope test` directive (Experimental)
5656
|

website/docs/commands/test.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ so [using directives](../guides/introduction/using-directives.md) can be used to
1616

1717
A source file is treated as test source if:
1818

19-
- the file name ends with `.test.scala`, or
19+
- the file name ends with `.test.scala` or `.test.java`, or
2020
- the file comes from a directory that is provided as input, and the relative path from that file to its original
2121
directory contains a `test` directory, or
2222
- it contains the `//> using target.scope test` directive
@@ -55,7 +55,7 @@ Given that directory structure, let's analyze what file(s) will be treated as te
5555

5656
`scala-cli example` results in the following files being treated as test sources:
5757

58-
- `a.test.scala`, since it ends with `.test.scala`
58+
- `a.test.scala`, since it ends with `.test.scala` (the same applies to `.test.java` for Java sources)
5959
- `src/test/scala/b.scala`, since the path to that directory contains a directory named `test`
6060

6161
Note that `e.scala` is not treated as a test source since it lacks a parent directory in its relative path that is
@@ -71,7 +71,7 @@ contain `test` (the fact that the directory provided as input is named `test` do
7171
Directives take precedence over file or path names, so `using target.scope main` can be used to force `test/a.scala`
7272
or `a.test.scala` to not be treated as tests.
7373

74-
As a rule of thumb, we recommend naming all of your test files with the `.test.scala` suffix.
74+
As a rule of thumb, we recommend naming all of your test files with the `.test.scala` (or `.test.java` for Java sources) suffix.
7575

7676
## Test directives
7777

website/docs/reference/commands.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,11 @@ Accepts option groups: [benchmarking](./cli-options.md#benchmarking-options), [c
390390

391391
## test
392392

393-
Compile and test Scala code.
393+
Compile and test Scala (or Java) code.
394394

395395
Test sources are compiled separately (after the 'main' sources), and may use different dependencies, compiler options, and other configurations.
396396
A source file is treated as a test source if:
397-
- the file name ends with `.test.scala`
397+
- the file name ends with `.test.scala` or `.test.java`
398398
- the file comes from a directory that is provided as input, and the relative path from that file to its original directory contains a `test` directory
399399
- it contains the `//> using target.scope test` directive (Experimental)
400400

website/docs/reference/scala-command/commands.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ Accepts option groups: [benchmarking](./cli-options.md#benchmarking-options), [c
191191

192192
### test
193193

194-
Compile and test Scala code.
194+
Compile and test Scala (or Java) code.
195195

196196
Test sources are compiled separately (after the 'main' sources), and may use different dependencies, compiler options, and other configurations.
197197
A source file is treated as a test source if:
198-
- the file name ends with `.test.scala`
198+
- the file name ends with `.test.scala` or `.test.java`
199199
- the file comes from a directory that is provided as input, and the relative path from that file to its original directory contains a `test` directory
200200
- it contains the `//> using target.scope test` directive (Experimental)
201201

website/docs/reference/scala-command/runner-specification.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4069,11 +4069,11 @@ Aliases: `--fmt-version`
40694069
## `test` command
40704070
**SHOULD have for Scala Runner specification.**
40714071

4072-
Compile and test Scala code.
4072+
Compile and test Scala (or Java) code.
40734073

40744074
Test sources are compiled separately (after the 'main' sources), and may use different dependencies, compiler options, and other configurations.
40754075
A source file is treated as a test source if:
4076-
- the file name ends with `.test.scala`
4076+
- the file name ends with `.test.scala` or `.test.java`
40774077
- the file comes from a directory that is provided as input, and the relative path from that file to its original directory contains a `test` directory
40784078
- it contains the `//> using target.scope test` directive (Experimental)
40794079

0 commit comments

Comments
 (0)