Skip to content

Commit

Permalink
Enum values that repeat the same number become aliases.
Browse files Browse the repository at this point in the history
Fixes #1611
  • Loading branch information
thesamet committed Nov 22, 2023
1 parent 69241cc commit 0df652c
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## [0.11.15]
- When more than one enum values share the same number, the first one would
generate a case object as usual, and subsequent ones will value values
referencing the case object. This is consistent with the Java behavior (#1611)

## [0.11.14]
- Repeated extensions can now use arbitrary iterable types or any collection type there is a
CollectionAdapter for (#1509)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class ProtobufGenerator(
import ProtobufGenerator._

def printEnum(printer: FunctionalPrinter, e: EnumDescriptor): FunctionalPrinter = {
val name = e.scalaType.nameSymbol
val name = e.scalaType.nameSymbol
val valuesByNumber = e.getValues().asScala.groupBy(_.getNumber())
printer
.when(e.getOptions.getDeprecated) {
_.add(ProtobufGenerator.deprecatedAnnotation)
Expand Down Expand Up @@ -56,17 +57,27 @@ class ProtobufGenerator(
.add(s"sealed trait ${e.recognizedEnum.nameSymbol} extends $name")
.add(s"implicit def enumCompanion: _root_.scalapb.GeneratedEnumCompanion[$name] = this")
.newline
.print(e.getValues.asScala) { case (p, v) =>
.print(valuesByNumber) { case (p, (_, values)) =>
val v = values.head
p.call(generateScalaDoc(v))
.add("@SerialVersionUID(0L)")
.seq(v.annotationList)
.add(s"""case object ${v.scalaName.asSymbol} extends ${v.valueExtends
.mkString(" with ")} {
| val index = ${v.getIndex}
| val name = "${v.getName}"
| override def ${v.isName}: _root_.scala.Boolean = true
|}
|""".stripMargin)
.mkString(" with ")} {""")
.indented(
_.add(s"val index = ${v.getIndex}")
.add(s"""val name = "${v.getName}"""")
.print(values) { case (p, u) =>
p.add(s"override def ${u.isName}: _root_.scala.Boolean = true")
}
)
.add("}")
.print(values.tail) { case (p, u) =>
p.call(generateScalaDoc(u))
.seq(u.annotationList)
.add(s"@transient val ${u.scalaName.asSymbol} = ${v.scalaName.asSymbol}")
}
.add("")
}
.add("@SerialVersionUID(0L)")
.seq(e.unrecognizedAnnotationList)
Expand Down
11 changes: 11 additions & 0 deletions e2e-withjava/src/main/protobuf/enum_alias.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";

package com.thesamet.proto.e2e;

enum EnumAllowingAlias {
option allow_alias = true;
EAA_UNSPECIFIED = 0;
EAA_STARTED = 1;
EAA_RUNNING = 1; // some doc
EAA_FINISHED = 2;
}
17 changes: 17 additions & 0 deletions e2e/src/test/scala/EnumAliasSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import com.thesamet.proto.e2e.enum_alias._
import org.scalatest._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers

class EnumAliasSpec extends AnyFlatSpec with Matchers with OptionValues {
"aliased enums" should "be equal" in {
EnumAllowingAlias.EAA_RUNNING must be(EnumAllowingAlias.EAA_STARTED)
}

it should "report isX true for all aliases" in {
EnumAllowingAlias.EAA_RUNNING.isEaaRunning must be(true)
EnumAllowingAlias.EAA_RUNNING.isEaaStarted must be(true)
EnumAllowingAlias.EAA_FINISHED.isEaaStarted must be(false)
EnumAllowingAlias.EAA_FINISHED.isEaaRunning must be(false)
}
}

0 comments on commit 0df652c

Please sign in to comment.