Skip to content

Commit deb5dbb

Browse files
committed
fix: enhance transientDefault handling to warn when no default value is provided
1 parent 38edf3b commit deb5dbb

File tree

2 files changed

+36
-6
lines changed

2 files changed

+36
-6
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.avsystem.commons.serialization
2+
3+
import org.scalatest.funsuite.AnyFunSuite
4+
5+
final class NotUsedTransientDefault extends AnyFunSuite {
6+
7+
test("no warnings when @transientDefault is used properly") {
8+
assertCompiles(
9+
//language=Scala
10+
s"""
11+
|case class X(@transientDefault a: String = "default")
12+
|val codec = GenCodec.materialize[X]
13+
|""".stripMargin
14+
)
15+
}
16+
17+
test("warnings when missing default value") {
18+
assertDoesNotCompile(
19+
//language=Scala
20+
s"""
21+
|case class X(@transientDefault a: String)
22+
|val codec = GenCodec.materialize[X]
23+
|""".stripMargin
24+
)
25+
}
26+
}

macros/src/main/scala/com/avsystem/commons/macros/serialization/GenCodecMacros.scala

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,13 @@ class GenCodecMacros(ctx: blackbox.Context) extends CodecMacroCommons(ctx) with
131131
}
132132
}
133133

134-
def isTransientDefault(param: ApplyParam): Boolean =
135-
param.defaultValue.nonEmpty && hasAnnotation(param.sym, TransientDefaultAnnotType)
136-
134+
def isTransientDefault(param: ApplyParam, warnIfDefaultNotProvided: Boolean = false): Boolean =
135+
(hasAnnotation(param.sym, TransientDefaultAnnotType), param.defaultValue.nonEmpty, warnIfDefaultNotProvided) match {
136+
case (true, false, true) =>
137+
c.warning(param.sym.pos, s"@transientDefault has no effect on parameter ${param.sym.name} because it has no default value")
138+
false
139+
case (hasAnnotation, noDefaultValue, _) => hasAnnotation && noDefaultValue
140+
}
137141
def isOptimizedPrimitive(param: ApplyParam): Boolean = {
138142
val vt = param.valueType
139143
vt =:= typeOf[Boolean] || vt =:= typeOf[Int] || vt =:= typeOf[Long] || vt =:= typeOf[Double]
@@ -251,13 +255,13 @@ class GenCodecMacros(ctx: blackbox.Context) extends CodecMacroCommons(ctx) with
251255
}
252256

253257
def anyParamHasTransientDefault: Boolean =
254-
params.exists(isTransientDefault)
258+
params.exists(isTransientDefault(_))
255259

256260
def isOptionLike(p: ApplyParam): Boolean =
257261
p.optionLike.nonEmpty
258262

259263
def mayBeTransient(p: ApplyParam): Boolean =
260-
isOptionLike(p) || isTransientDefault(p)
264+
isOptionLike(p) || isTransientDefault(p, warnIfDefaultNotProvided = true)
261265

262266
def transientValue(p: ApplyParam): Tree = p.optionLike match {
263267
case Some(optionLike) => q"${optionLike.reference(Nil)}.none"
@@ -614,7 +618,7 @@ class GenCodecMacros(ctx: blackbox.Context) extends CodecMacroCommons(ctx) with
614618
val deps = new mutable.ListBuffer[Tree]
615619

616620
ttpe.members.iterator.foreach { getter =>
617-
if(getter.isMethod && isJavaGetter(getter.asMethod)) {
621+
if (getter.isMethod && isJavaGetter(getter.asMethod)) {
618622
val propType = getter.typeSignatureIn(ttpe).finalResultType
619623
val getterName = getter.name.decodedName.toString
620624
val setterName = getterName.replaceFirst("^(get|is)", "set")

0 commit comments

Comments
 (0)