Skip to content

Commit f422418

Browse files
authored
Add support for marking certain types as serializable via sbt configuration (and not via @SerializabilityTrait) (#304)
Add support for marking certain types as serializable via configuration (and not via `@SerializabilityTrait`)
1 parent 75a6d66 commit f422418

9 files changed

+88
-1
lines changed

docs/GUIDE.md

+7
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ This option disables detection of messages/events/state based on type of argumen
118118
This option disables detection of messages/events/state based on return type of the function given as argument to method. This detection is enabled by default. If you want to disable it, add the following setting:<br>
119119
`Compile / scalacOptions += "-P:serializability-checker-plugin:--disable-detection-higher-order-function"`<br><br>
120120

121+
- `--types-explicitly-marked-as-serializable=<type1>,<type2>,...`
122+
123+
This option can be used to pass a comma-separated list of fully-qualified names of types that should be considered serializable by the checker, even if they do **not** extend a designated serializability trait.
124+
The list is empty by default. If you want to mark some types as serializable, add the following setting (here shown with sample types):<br>
125+
126+
`Compile / scalacOptions += "-P:serializability-checker-plugin:--types-explicitly-marked-as-serializable=scala.util.Either,scala.collection.immutable.Set"`<br><br>
127+
121128
### Codec Registration Checker Compiler Plugin
122129
Before using this compiler plugin, make sure that you are using both [annotations](#annotations) properly. If so &mdash; the plugin can be used right away. This plugin checks whether classes marked with serializability trait are being referenced in a marked serializer, which ensures that codecs will be registered in runtime.
123130

serializability-checker-compiler-plugin/src/main/scala/org/virtuslab/ash/SerializabilityCheckerCompilerPlugin.scala

+6
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class SerializabilityCheckerCompilerPlugin(override val global: Global) extends
2727
pluginOptions.detectFromMethods = !options.contains(disableMethods)
2828
pluginOptions.detectFromUntypedMethods = !options.contains(disableMethodsUntyped)
2929
pluginOptions.detectFromHigherOrderFunctions = !options.contains(disableHigherOrderFunctions)
30+
options.find(_.startsWith(typesExplicitlyMarkedAsSerializable)).foreach { opt =>
31+
pluginOptions.typesExplicitlyMarkedAsSerializable =
32+
opt.stripPrefix(typesExplicitlyMarkedAsSerializable).split(",").toSeq.map(_.strip())
33+
}
3034
true
3135
}
3236

@@ -37,6 +41,7 @@ class SerializabilityCheckerCompilerPlugin(override val global: Global) extends
3741
|$disableMethods - disables detection of messages/events/state based on type of arguments to a method, e.g. akka.actor.typed.ActorRef.tell
3842
|$disableMethodsUntyped - disables detection of messages/events/state based on type of arguments to a method that takes Any, used for Akka Classic
3943
|$disableHigherOrderFunctions - disables detection of messages/events/state based on return type of the function given as argument to method
44+
|$typesExplicitlyMarkedAsSerializable - comma-separated list of fully-qualified names of types that should be considered serializable by this checker, even if they do NOT extend a designated serializability trait
4045
|""".stripMargin)
4146
}
4247

@@ -49,6 +54,7 @@ object SerializabilityCheckerCompilerPlugin {
4954
val disableMethods = "--disable-detection-methods"
5055
val disableMethodsUntyped = "--disable-detection-untyped-methods"
5156
val disableHigherOrderFunctions = "--disable-detection-higher-order-function"
57+
val typesExplicitlyMarkedAsSerializable = "--types-explicitly-marked-as-serializable="
5258
}
5359
val serializabilityTraitType = "org.virtuslab.ash.annotation.SerializabilityTrait"
5460
}

serializability-checker-compiler-plugin/src/main/scala/org/virtuslab/ash/SerializabilityCheckerCompilerPluginComponent.scala

+2
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ class SerializabilityCheckerCompilerPluginComponent(
192192
Some(tp)
193193
else if (akkaSerializabilityTraits.contains(tp.typeSymbol.fullName))
194194
Some(tp)
195+
else if (pluginOptions.typesExplicitlyMarkedAsSerializable.contains(tp.typeSymbol.fullName))
196+
Some(tp)
195197
else if (tp.typeSymbol.isAbstractType)
196198
findSuperclassAnnotatedWithSerializabilityTrait(tp.upperBound)
197199
else

serializability-checker-compiler-plugin/src/main/scala/org/virtuslab/ash/SerializabilityCheckerOptions.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ class SerializabilityCheckerOptions(
1010
var detectFromGenericMethods: Boolean = true,
1111
var detectFromMethods: Boolean = true,
1212
var detectFromUntypedMethods: Boolean = true,
13-
var detectFromHigherOrderFunctions: Boolean = true)
13+
var detectFromHigherOrderFunctions: Boolean = true,
14+
var typesExplicitlyMarkedAsSerializable: Seq[String] = Seq.empty)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.random.project
2+
3+
import akka.actor.ActorRef
4+
5+
object TellEitherSeqSetTest {
6+
7+
val ref: ActorRef = ???
8+
ref.tell(Right("hello"), null)
9+
ref.tell(Seq("hello"), null)
10+
ref.tell(Set("hello"), null)
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.random.project
2+
3+
import akka.actor.ActorRef
4+
5+
object TellEitherTest {
6+
7+
val ref: ActorRef = ???
8+
ref.tell(Right("hello"), null)
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.random.project
2+
3+
import akka.actor.ActorRef
4+
5+
object TellSeqTest {
6+
7+
val ref: ActorRef = ???
8+
ref.tell(Seq("hello"), null)
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.random.project
2+
3+
import akka.actor.ActorRef
4+
5+
object TellSetTest {
6+
7+
val ref: ActorRef = ???
8+
ref.tell(Set("hello"), null)
9+
}

serializability-checker-compiler-plugin/src/test/scala/org/virtuslab/ash/SerializabilityCheckerCompilerPluginComponentSpec.scala

+33
Original file line numberDiff line numberDiff line change
@@ -180,5 +180,38 @@ class SerializabilityCheckerCompilerPluginComponentSpec extends AnyWordSpecLike
180180
val code = getResourceAsString("GenericsTest3.scala")
181181
SerializabilityCheckerCompiler.compileCode(List(serNoCode, code)) should be("")
182182
}
183+
184+
"fail on usage of Either as a message" in {
185+
val code = getResourceAsString("TellEitherTest.scala")
186+
SerializabilityCheckerCompiler.compileCode(List(code)) should include(
187+
"Right[Nothing,String] is used as Akka message")
188+
}
189+
190+
"fail on usage of Seq as a message" in {
191+
val code = getResourceAsString("TellSeqTest.scala")
192+
SerializabilityCheckerCompiler.compileCode(List(code)) should include("Seq[String] is used as Akka message")
193+
}
194+
195+
"fail on usage of Set as a message" in {
196+
val code = getResourceAsString("TellSetTest.scala")
197+
SerializabilityCheckerCompiler.compileCode(List(code)) should include("Set[String] is used as Akka message")
198+
}
199+
200+
"not fail on usage of Either as a message when Either is explicitly marked as serializable" in {
201+
val code = getResourceAsString("TellEitherTest.scala")
202+
SerializabilityCheckerCompiler.compileCode(
203+
List(code),
204+
List(typesExplicitlyMarkedAsSerializable + "scala.util.Either")) should be("")
205+
}
206+
207+
"when multiple types are used as a message, then only fail on the ones that are NOT explicitly marked as serializable" in {
208+
val code = getResourceAsString("TellEitherSeqSetTest.scala")
209+
val output = SerializabilityCheckerCompiler.compileCode(
210+
List(code),
211+
List(typesExplicitlyMarkedAsSerializable + "scala.util.Either,scala.collection.immutable.Set"))
212+
output should include("Seq[String] is used as Akka message")
213+
(output should not).include("Right[Nothing,String] is used as Akka message")
214+
(output should not).include("Set[String] is used as Akka message")
215+
}
183216
}
184217
}

0 commit comments

Comments
 (0)