Skip to content

Added Scala 3 support#1904

Open
rozza wants to merge 3 commits intomongodb:mainfrom
rozza:JAVA-5261
Open

Added Scala 3 support#1904
rozza wants to merge 3 commits intomongodb:mainfrom
rozza:JAVA-5261

Conversation

@rozza
Copy link
Member

@rozza rozza commented Mar 3, 2026

Added Macro support for Scala 3
Split Scala code to Scala 2 and Scala 3 specific code Updated evergreen to test Scala 3
Updated spotless Scala configuration to default to Scala 2 Added custom spotless Scala configuration for Scala 3 in bson-scala Updated test code work both with Scala 2 and Scala 3

JAVA-5261

@rozza rozza force-pushed the JAVA-5261 branch 6 times, most recently from 6dd3f40 to 71cab33 Compare March 3, 2026 16:03
@rozza
Copy link
Member Author

rozza commented Mar 3, 2026

Added Macro support for Scala 3
Split Scala code to Scala 2 and Scala 3 specific code
Updated evergreen to test Scala 3
Updated spotless Scala configuration to default to Scala 2
Added custom spotless Scala configuration for Scala 3 in bson-scala
Updated test code work both with Scala 2 and Scala 3

JAVA-5261
- name: "scala-test-task"

- matrix_name: "scala-tests-3"
matrix_spec: { auth: "noauth", ssl: "nossl", jdk: [ "jdk17", "jdk21" ], version: [ "8.0" ], topology: "replicaset",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scala 3 currently supports Java 8.

However, with Java 8 some of the test Models caused scalatest-Junit to fail with invalid class name.

Unfortunately, the fix is to upgrade scalatest but doing that limits the base version of the SDK - so I opted not test against Java 8, rather than set a hard base of 17.


scalaVersions?.forEach { version ->
require(version.matches(Regex("\\d\\.\\d{2}"))) { "Scala version '$version' must be in the format X.YY" }
require(version.matches(Regex("^[23].*"))) { "Scala version '$version' not supported." }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to ensure the bom is correctly configured.

Where as Scala 2.11, 2.12, 2.13 are all major releases. Scala 3 has gone for the traditional Major.Minor.Patch formatting.

This means the postfix for artifacts for scala 3 is just _3 where as Scala 2 variants are _2.11, _2.12 etc. eg: mongo-scala-driver_2.11

case BsonType.DOCUMENT => readDocument(reader, decoderContext, clazz, typeArgs)
case BsonType.ARRAY => readArray(reader, decoderContext, clazz, typeArgs)
case BsonType.NULL =>
case BsonType.NULL =>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scalafmt changes only and a move to scala2 source directory

*
* @see [[MacroCodec]] for the runtime base trait that the generated codec extends.
*/
private[bson] object CaseClassCodec {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core of the CaseClassCodec Macro. It follows the same patterns as the Scala 2 version.

Scala 3 totally rewrote the Macros in a non compatible way. So this version is updated for the new Scala 3 macros and compile time reflection.

@@ -0,0 +1,141 @@
/*
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scala 3 versions of Document and BaseBsonDocument using Scala 3 specific classes.

Much the same as the Scala 2.13 version. But I didn't want to split out joint Scala 2.13 & Scala 3 code as the source directories are confusing enough.

scala {
target("**/*.scala")
scalafmt().configFile(rootProject.file("config/scala/scalafmt.conf"))
targetExclude("**/scala-3/**")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default excludes all scala-3 code.

// ============================================
val compileOptions = mutableListOf("-target:jvm-1.8")
when (scalaVersion) {
"3" -> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds the Scala 3 code base with its own specific sourcesets.


package org.mongodb.scala.documentation

import java.util.concurrent.CountDownLatch
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these test changes were needed to ensure the tests work in both Scala 2 and Scala 3.

Implicit conversions now have to be explicitly imported in Scala 3. Some Scala 3 language based implicits where previously used (eg maxTime auto conversion to Duration). This is now explicit so that it can work across versions.

Partial functions are required to be ( varname: Type) => where as previously they could be without parenthesis.

Functions that are defined with parenthesis, must include them in Scala 3 eg: collection.watch was fine in Scala 2, but now must be collection.watch().


abstract class BaseSpec extends AnyFlatSpec with Matchers {}
abstract class BaseSpec extends AnyFlatSpec with Matchers {
val DEFAULT_EXCLUSIONS: Set[String] =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I DRY'd up the default exclusions. Depending on the version of Scala depends on the name of some of the auto added methods to java / scala classes when relfecting on the methods in the API.

org.gradle.jvmargs=-Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en
## NOTE: This property is also used to generate scala compile versions in BOM.
supportedScalaVersions=2.13,2.12,2.11
supportedScalaVersions=3,2.13,2.12,2.11
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@rozza rozza marked this pull request as ready for review March 4, 2026 10:11
@rozza rozza requested a review from a team as a code owner March 4, 2026 10:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Scala 3 support across the Scala driver and BSON Scala modules, including Scala 3 macro-based codecs, version-specific source set wiring, updated formatting (Spotless/scalafmt) configuration, and Evergreen CI coverage.

Changes:

  • Add Scala 3 as a supported build/test target (Gradle properties, BOM validation, Evergreen matrix).
  • Split Scala sources/tests into Scala 2 vs Scala 3 source sets and update Scala build wiring/dependencies.
  • Add Scala 3 macro codec implementation + Scala 3-specific BSON collection code and tests.

Reviewed changes

Copilot reviewed 79 out of 87 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Adds Scala 3 library/test coordinates and bumps tool/test versions.
gradle.properties Adds Scala 3 to supportedScalaVersions.
driver-scala/src/test/scala/org/mongodb/scala/model/ValidationLevelSpec.scala Uses shared DEFAULT_EXCLUSIONS for reflection-based API parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/ValidationActionSpec.scala Uses shared DEFAULT_EXCLUSIONS for reflection-based API parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/ProjectionsSpec.scala Adjusts method invocation to be Scala 3-compatible.
driver-scala/src/test/scala/org/mongodb/scala/model/MergeOptionsSpec.scala Updates exclusions for Scala 3 method synthesis differences.
driver-scala/src/test/scala/org/mongodb/scala/model/FiltersSpec.scala Updates exclusions for Scala 3 compiler-synthesized methods.
driver-scala/src/test/scala/org/mongodb/scala/model/CollationStrengthSpec.scala Uses shared DEFAULT_EXCLUSIONS for parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/CollationSpec.scala Uses shared DEFAULT_EXCLUSIONS for parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/CollationMaxVariableSpec.scala Uses shared DEFAULT_EXCLUSIONS for parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/CollationCaseFirstSpec.scala Uses shared DEFAULT_EXCLUSIONS for parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/CollationAlternateSpec.scala Uses shared DEFAULT_EXCLUSIONS for parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/BucketGranularitySpec.scala Uses shared DEFAULT_EXCLUSIONS for parity test.
driver-scala/src/test/scala/org/mongodb/scala/model/AggregatesSpec.scala Adds import to support Scala 3 compilation changes.
driver-scala/src/test/scala/org/mongodb/scala/internal/ScalaObservableSpec.scala Tweaks syntax/class definitions for Scala 3 compatibility.
driver-scala/src/test/scala/org/mongodb/scala/internal/FlatMapObservableTest.scala Fixes Promise completion call signature for Scala 3.
driver-scala/src/test/scala/org/mongodb/scala/internal/CollectObservableTest.scala Adds ObservableFuture import for Scala 3 compilation.
driver-scala/src/test/scala/org/mongodb/scala/connection/ConnectionSpec.scala Updates builder invocation style for Scala 3.
driver-scala/src/test/scala/org/mongodb/scala/ReadPreferenceSpec.scala Updates exclusions and formatting for Scala 3.
driver-scala/src/test/scala/org/mongodb/scala/ReadConcernSpec.scala Uses DEFAULT_EXCLUSIONS for Scala 3 compiler methods.
driver-scala/src/test/scala/org/mongodb/scala/ReadConcernLevelSpec.scala Uses DEFAULT_EXCLUSIONS for Scala 3 compiler methods.
driver-scala/src/test/scala/org/mongodb/scala/ObservableImplicitsToGridFSUploadPublisherUnitSpec.scala Adds explicit type to satisfy Scala 3 inference.
driver-scala/src/test/scala/org/mongodb/scala/MongoDriverInformationSpec.scala Consolidates exclusions via DEFAULT_EXCLUSIONS.
driver-scala/src/test/scala/org/mongodb/scala/DistinctObservableSpec.scala Refactors exclusions to include DEFAULT_EXCLUSIONS.
driver-scala/src/test/scala/org/mongodb/scala/CreateIndexCommitQuorumSpec.scala Excludes Scala 3 synthetic methods via DEFAULT_EXCLUSIONS.
driver-scala/src/test/scala/org/mongodb/scala/BaseSpec.scala Introduces DEFAULT_EXCLUSIONS shared by multiple tests.
driver-scala/src/test/scala-2/org/mongodb/scala/ApiAliasAndCompanionSpec.scala Formatting tweak for Scala 2 specific tests.
driver-scala/src/integrationTest/scala/tour/QuickTourCaseClass.scala Updates find/first call chain for Scala 3 compatibility.
driver-scala/src/integrationTest/scala/tour/QuickTour.scala Updates find/first call chain and lambda syntax for Scala 3.
driver-scala/src/integrationTest/scala/tour/Helpers.scala Updates toJson invocation for Scala 3.
driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionExplicitEncryptionOnlyTour.scala Updates find/first call chain for Scala 3.
driver-scala/src/integrationTest/scala/tour/ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala Updates find/first call chain for Scala 3.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoIterable.scala Import ordering cleanup.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoDatabase.scala Adapts timeouts to Duration-based APIs.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCursor.scala Import ordering and minor match formatting.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCollection.scala Adds futures imports used by updated APIs.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMongoCluster.scala Adds futures import for updated APIs.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncMapReduceIterable.scala Adapts maxTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListSearchIndexesIterable.scala Adapts maxTime and explain signatures for Scala 3 typing.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListIndexesIterable.scala Adapts maxTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListDatabasesIterable.scala Adapts maxTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncListCollectionsIterable.scala Adapts maxTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncFindIterable.scala Adapts maxTime/maxAwaitTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncDistinctIterable.scala Adapts maxTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncClientSession.scala Import ordering cleanup.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncClientEncryption.scala Adds conversion import for updated BSON APIs.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncChangeStreamIterable.scala Adapts maxAwaitTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/syncadapter/SyncAggregateIterable.scala Adapts maxTime/maxAwaitTime to Duration-based API.
driver-scala/src/integrationTest/scala/org/mongodb/scala/gridfs/GridFSObservableSpec.scala Scala 3 syntax adjustments (type params, class defs).
driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationTransactionsExampleSpec.scala Updates helper invocation style for Scala 3.
driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationExampleSpec.scala Updates helpers, watch() invocation, observer class for Scala 3.
driver-scala/src/integrationTest/scala/org/mongodb/scala/documentation/DocumentationChangeStreamExampleSpec.scala Updates watch() invocation and lambda syntax for Scala 3.
driver-scala/src/integrationTest/scala/org/mongodb/scala/TestMongoClientHelper.scala Converts helpers to explicit nullary methods + local WAIT_DURATION.
driver-scala/src/integrationTest/scala/org/mongodb/scala/RequiresMongoDBISpec.scala Updates helper calls/signatures for Scala 3.
driver-scala/README.md Documents Scala version support, source layout, Spotless, and testing flags.
config/scala/scalafmt-3.conf Adds Scala 3-specific scalafmt configuration.
config/scala/scalafmt-2.conf Updates Scala 2 scalafmt version.
buildSrc/src/main/kotlin/project/scala.gradle.kts Adds Scala 3 dependency wiring and source set configuration.
buildSrc/src/main/kotlin/conventions/spotless.gradle.kts Defaults Spotless to Scala 2 config and excludes scala-3 paths.
bson-scala/src/test/scala/org/mongodb/scala/bson/collections/MutableDocumentSpec.scala Formatting adjustments for Scala 3 compatibility.
bson-scala/src/test/scala/org/mongodb/scala/bson/collections/ImmutableDocumentSpec.scala Formatting adjustments for Scala 3 compatibility.
bson-scala/src/test/scala/org/mongodb/scala/bson/codecs/MutableDocumentCodecSpec.scala Formatting adjustments for Scala 3 compatibility.
bson-scala/src/test/scala/org/mongodb/scala/bson/codecs/ImmutableDocumentCodecSpec.scala Formatting adjustments for Scala 3 compatibility.
bson-scala/src/test/scala-3/org/mongodb/scala/bson/codecs/Models.scala Adds Scala 3 test models for macro codec coverage.
bson-scala/src/test/scala-3/org/mongodb/scala/bson/codecs/MacrosSpec.scala Adds Scala 3 macro codec spec suite.
bson-scala/src/test/scala-2/org/mongodb/scala/bson/codecs/MacrosSpec.scala Import/order formatting tweaks for Scala 2 suite.
bson-scala/src/main/scala/org/mongodb/scala/bson/codecs/IterableCodec.scala Minor formatting update.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/collection/package.scala Scala 3 package object for collection Document alias.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/collection/mutable/Document.scala Scala 3 mutable Document implementation.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/collection/immutable/Document.scala Scala 3 immutable Document implementation.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/collection/BaseDocument.scala Scala 3 BaseDocument implementation.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/codecs/macrocodecs/MacroCodec.scala Scala 3 runtime macro codec base implementation.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/codecs/macrocodecs/CaseClassProvider.scala Scala 3 macro entry point for codec providers.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/codecs/macrocodecs/CaseClassCodec.scala Scala 3 macro that generates codecs.
bson-scala/src/main/scala-3/org/mongodb/scala/bson/codecs/Macros.scala Scala 3 public macro API (inline/quoted) surface.
bson-scala/src/main/scala-2/org/mongodb/scala/bson/collection/package.scala Scala 2 package object for collection Document alias.
bson-scala/src/main/scala-2/org/mongodb/scala/bson/collection/BaseDocument.scala Scala 2 BaseDocument implementation.
bson-scala/src/main/scala-2/org/mongodb/scala/bson/codecs/macrocodecs/MacroCodec.scala Scala 2 macro codec runtime tweaks/formatting.
bson-scala/src/main/scala-2/org/mongodb/scala/bson/codecs/macrocodecs/CaseClassProvider.scala Scala 2 macro provider wiring changes.
bson-scala/src/main/scala-2/org/mongodb/scala/bson/codecs/macrocodecs/CaseClassCodec.scala Scala 2 macro codec formatting tweak.
bson-scala/src/main/scala-2/org/mongodb/scala/bson/codecs/Macros.scala Scala 2 public macro API surface (macro defs).
bson-scala/src/main/scala-2.13/org/mongodb/scala/bson/collection/mutable/Document.scala Scala 2.13 mutable Document implementation.
bson-scala/src/main/scala-2.13/org/mongodb/scala/bson/collection/immutable/Document.scala Scala 2.13 immutable Document implementation.
bson-scala/build.gradle.kts Adds Scala-version-aware Spotless override for scala-3 sources.
bson-scala/README.md Documents Scala 3 support and module build/layout details.
bom/build.gradle.kts Updates Scala version validation to accept Scala 3.
.evergreen/.evg.yml Adds Scala 3 axis and build variants for Scala 3 testing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@rozza
Copy link
Member Author

rozza commented Mar 11, 2026

@copilot open a new pull request to apply changes based on the comments in this thread

OK that didn't happen (might be a config issue on the org) So manually did the changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants