Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend package choosing behavior to protobuf files with Enum types #339

Merged
merged 20 commits into from
Oct 24, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
cfdc57e
making my change downstream, walking fast, faces past and I'm /Users/…
dmartin-TA Sep 27, 2020
b3b96e8
there's no reason these tests don't work but they still don't so I ju…
dmarticus Sep 28, 2020
4b00c1e
test bed is created and my ideal behavior for a simple scenario works…
dmarticus Sep 28, 2020
d85e0be
make it so that we trim the type name based on the amount of nesting …
dmarticus Sep 28, 2020
316151f
added a comment to the method
dmartin-TA Sep 29, 2020
ff78c78
forgot to format
dmartin-TA Sep 29, 2020
eceff15
renaming the method to make it more explicit
dmartin-TA Oct 5, 2020
a39ceac
Merge branch 'master' into issue337
dmartin-TA Oct 5, 2020
77d2200
pushing a broken version to test a thing
dmartin-TA Oct 7, 2020
b02764b
Merge branch 'master' into issue337
dmarticus Oct 11, 2020
5cbb790
Merge branch 'master' into issue337
dmartin-TA Oct 17, 2020
f7ecbc6
this for sure works but it still doesn't leverage endsWith... I want …
dmartin-TA Oct 17, 2020
70df7d2
slightly betterer formatting
dmartin-TA Oct 17, 2020
419e97e
adding contextual content
dmartin-TA Oct 17, 2020
e7d6261
out with the string modifications, in with comparing packages
dmartin-TA Oct 22, 2020
3d12d9b
Merge branch 'master' into issue337
dmartin-TA Oct 22, 2020
c0522c5
Update src/main/scala/higherkindness/skeuomorph/protobuf/ParseProto.s…
Oct 23, 2020
d0e0a74
this should do it!
dmartin-TA Oct 23, 2020
dbafb2d
attempting to placate the all-powerful codecov bot
dmartin-TA Oct 23, 2020
e558de3
yeah bb that did it
dmarticus Oct 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/main/scala/higherkindness/skeuomorph/protobuf/ParseProto.scala
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,15 @@ object ParseProto {
// (which will return the fully-qualified name) vs accessing a type name from a file with a `java_package`
// header (which will just return the name of the type). This method trims the type name from a fully-
// qualified name if necessary, which provides consistent behavior when comparing the name of a message
// to the name of a type
fullName.substring(fullName.lastIndexOf(".") + 1)
// to the name of a type.
//
// In addition, the reason we count '.' characters is because the value of the FQN will be different
// depending on whether the fullName was generated from a protobuf file that used the `package` option,
// vs a protobuf file that used the `java_package`, or simply had an empty option. Therefore, we need
// to parse exactly as many dots as the FQN so that we extract exactly as much FQN as we need to use
// the type name appropriately. A more involved example explaining why we do this can be found here:
// https://github.com/higherkindness/skeuomorph/pull/339#discussion_r496969857
fullName.substring(fullName.indexOf(".", fullName.count(_ == '.')) + 1)
dmarticus marked this conversation as resolved.
Show resolved Hide resolved

def fromProto[A](
descriptorFileName: String,
Expand Down Expand Up @@ -473,7 +480,7 @@ object ParseProto {
}

(allTopLevel ++ allNestedInsideMessages)
.find(_.fullName === name)
.find(_.fullName.contains(getTypeNameFromQualifiedName(name)))
}

implicit class LabelOps(self: Label) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ class ProtobufProtocolSpec extends Specification with ScalaCheck {
The generated Scala code should use the `java_package` option when both `package` and `java_package` are present in a file. $codeGenProtobufJavaPackage

The generated Scala code should use the filename as a package option when neither `package` nor `java_package` are present in a file. $codegenProtobufNoPackage

The generated Scala code should handle enums when `package` is present in a file. $codeGenProtobufEnumWithPackage

The generated Scala code should handle enums when neither `package` nor `java_package` in a file. $codeGenProtobufEnumWithNoPackage

"""

private def codegenProtobufProtocol =
Expand Down Expand Up @@ -457,4 +462,53 @@ class ProtobufProtocolSpec extends Specification with ScalaCheck {
|}
|""".stripMargin

private def codeGenProtobufEnumWithPackage = {
val enumWithPackage: Protocol[Mu[ProtobufF]] = {
val path = workingDirectory + s"$testDirectory/packages"
val source = ProtoSource(s"test_enum_package.proto", path, importRoot)
parseProto[IO, Mu[ProtobufF]].parse(source).unsafeRunSync()
}

check(enumWithPackage, protobufEnumWithPackageExpectation)
}

val protobufEnumWithPackageExpectation =
s"""
|package example
|import _root_.higherkindness.mu.rpc.protocol._
|object test_enum_package {
| final case class Example(@_root_.pbdirect.pbIndex(1) enum: _root_.scala.Option[_root_.example.test_enum_package.ExampleEnum])
| sealed abstract class ExampleEnum(val value: _root_.scala.Int) extends _root_.enumeratum.values.IntEnumEntry
| object ExampleEnum extends _root_.enumeratum.values.IntEnum[ExampleEnum] {
| case object Option1 extends ExampleEnum(0)
| case object Option2 extends ExampleEnum(1)
| val values = findValues
| }
|}
|""".stripMargin

private def codeGenProtobufEnumWithNoPackage = {
val enumWithNoPackage: Protocol[Mu[ProtobufF]] = {
val path = workingDirectory + s"$testDirectory/packages"
val source = ProtoSource(s"test_enum_no_package.proto", path, importRoot)
parseProto[IO, Mu[ProtobufF]].parse(source).unsafeRunSync()
}

check(enumWithNoPackage, protobufEnumWithoutPackageExpectation)
}

val protobufEnumWithoutPackageExpectation =
s"""
|package test_enum_no_package
|import _root_.higherkindness.mu.rpc.protocol._
|object test_enum_no_package {
| final case class Example(@_root_.pbdirect.pbIndex(1) enum: _root_.scala.Option[_root_.test_enum_no_package.test_enum_no_package.ExampleEnum])
| sealed abstract class ExampleEnum(val value: _root_.scala.Int) extends _root_.enumeratum.values.IntEnumEntry
| object ExampleEnum extends _root_.enumeratum.values.IntEnum[ExampleEnum] {
| case object Option1 extends ExampleEnum(0)
| case object Option2 extends ExampleEnum(1)
| val values = findValues
| }
|}
|""".stripMargin
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto3";

message Example {
ExampleEnum enum = 1;
}

enum ExampleEnum {
Option1 = 0;
Option2 = 1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
syntax = "proto3";

package example;

message Example {
ExampleEnum enum = 1;
}

enum ExampleEnum {
Option1 = 0;
Option2 = 1;
}