Skip to content

Commit

Permalink
Add option to block generation/access to field getters (scalapb#1140)
Browse files Browse the repository at this point in the history
Add option to block generation/access to field getters
  • Loading branch information
tOverney authored May 14, 2021
1 parent d113403 commit 3590047
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 49 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Change Log
## [0.11.2] (Unreleased)
- Fix bug where generated code would not compile if a message was named Unit (#1126)
- Add option to block generation/access to field getters (#1098)
-
## [0.11.1]
- Support Scala 3.0.0-RC2
Expand Down
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ lazy val compilerPlugin = (projectMatrix in file("compiler-plugin"))
),
mimaPreviousArtifacts := Set("com.thesamet.scalapb" %% "compilerplugin" % MimaPreviousVersion),
mimaBinaryIssueFilters := Seq(
ProblemFilters.exclude[ReversedMissingMethodProblem]("scalapb.options.*")
),
PB.protocVersion := protobufCompilerVersion,
Compile / PB.targets := Seq(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,9 @@ class DescriptorImplicits private[compiler] (
(message.getFile.scalaOptions.getLenses)
else params.lenses

def generateGetters: Boolean =
message.getFile.scalaOptions.getGetters

def baseClasses: Seq[String] = {
val specialMixins = message.getFullName match {
case "google.protobuf.Any" => Seq("_root_.scalapb.AnyMethods")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1326,10 +1326,13 @@ class ProtobufGenerator(
val clearMethod = "clear" + field.upperScalaName
val singleType = field.singleScalaTypeName
printer
.when(field.supportsPresence || field.isInOneof) { p =>
.when(
(field.supportsPresence || field.isInOneof) && (message.generateGetters || message.generateLenses)
) { p =>
val default = defaultValueForGet(field)
val scope = if (message.generateGetters) "" else "private "
p.add(
s"def ${field.getMethod}: ${field.singleScalaTypeName} = ${fieldAccessorSymbol(field)}.getOrElse($default)"
s"${scope}def ${field.getMethod}: ${field.singleScalaTypeName} = ${fieldAccessorSymbol(field)}.getOrElse($default)"
)
}
.when(field.supportsPresence) { p =>
Expand Down
2 changes: 2 additions & 0 deletions docs/src/main/markdown/customizations.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ option (scalapb.options) = {
preamble: "sealed trait BaseMessage"
preamble: "sealed trait CommonMessage"
lenses: true
getters: true
retain_source_code_info: false
no_default_values_in_constructor: false
preserve_unknown_fields: false
Expand Down Expand Up @@ -91,6 +92,7 @@ enums to a single Scala file.
with other things in your project.

- Setting `lenses` to `false` inhibits generation of lenses (default is `true`).
- Setting `getters` to `false` inhibits generation of getters (default is `true`).

- Setting `retain_source_code_info` to `true` retains information in the descriptor that
can be used to retrieve source code information from the descriptor at
Expand Down
15 changes: 15 additions & 0 deletions e2e/src/main/protobuf/nocode/no_getters.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax = "proto3";

package scalapb.e2e;

option (scalapb.options).getters = false;

import "scalapb/scalapb.proto";

message NoGettersA {
int32 a = 1;
}

message NoGetters {
NoGettersA a = 1;
}
18 changes: 18 additions & 0 deletions e2e/src/main/protobuf/nocode/no_getters_or_lenses.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

package scalapb.e2e;

option (scalapb.options) = {
lenses: false
getters: false
};

import "scalapb/scalapb.proto";

message NoGettersOrLensesA {
int32 a = 1;
}

message NoGettersOrLenses {
NoGettersOrLensesA a = 1;
}
6 changes: 5 additions & 1 deletion e2e/src/main/protobuf/nocode/no_lenses.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ option (scalapb.options).lenses = false;

import "scalapb/scalapb.proto";

message NoLenses {
message NoLensesA {
int32 a = 1;
}

message NoLenses {
NoLensesA a = 1;
int32 b = 2;
}
32 changes: 32 additions & 0 deletions e2e/src/test/scala/NoGettersSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.must.Matchers
import scalapb.e2e.no_getters._
import scalapb.e2e.no_getters_or_lenses._
import scalapb.e2e.no_lenses._

class NoGettersSpec extends AnyFlatSpec with Matchers {
val noGetters = NoGetters(a = Some(NoGettersA(12)))

"getters" should "not be available but lenses should function" in {
noGetters.a mustBe defined
assertDoesNotCompile("noGetters.getA")
noGetters.update(_.a := NoGettersA(12))
}

val noGettersOrLenses = NoGettersOrLenses(a = Some(NoGettersOrLensesA(12)))

it should "not exist at all if lenses do not exist either" in {
noGettersOrLenses.a mustBe defined

assertDoesNotCompile("noGettersOrLenses.update(_.a := NoGettersOrLensesA(11))")
assertDoesNotCompile("noGettersOrLenses.getA")
}

val noLenses = NoLenses(a = Some(NoLensesA(12)), b = 12)

it should "still exist even if lenses are disabled" in {
noLenses.a mustBe defined
noLenses.getA.a mustBe 12
assertDoesNotCompile("noLenses.update(_.a := NoLensesA(11))")
}
}
3 changes: 3 additions & 0 deletions protobuf/scalapb/scalapb.proto
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ message ScalaPbOptions {
// opt out from transformations inherited through package-scoped options.
optional bool ignore_all_transformations = 26;

// If true, getters will be generated.
optional bool getters = 27 [default=true];

// For use in tests only. Inhibit Java conversions even when when generator parameters
// request for it.
optional bool test_only_no_java_conversions = 999;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ package scalapb.options
* @param ignoreAllTransformations
* Ignores all transformations for this file. This is meant to allow specific files to
* opt out from transformations inherited through package-scoped options.
* @param getters
* If true, getters will be generated.
* @param testOnlyNoJavaConversions
* For use in tests only. Inhibit Java conversions even when when generator parameters
* request for it.
Expand Down Expand Up @@ -107,6 +109,7 @@ final case class ScalaPbOptions(
preprocessors: _root_.scala.Seq[_root_.scala.Predef.String] = _root_.scala.Seq.empty,
fieldTransformations: _root_.scala.Seq[scalapb.options.FieldTransformation] = _root_.scala.Seq.empty,
ignoreAllTransformations: _root_.scala.Option[_root_.scala.Boolean] = _root_.scala.None,
getters: _root_.scala.Option[_root_.scala.Boolean] = _root_.scala.None,
testOnlyNoJavaConversions: _root_.scala.Option[_root_.scala.Boolean] = _root_.scala.None,
unknownFields: _root_.scalapb.UnknownFieldSet = _root_.scalapb.UnknownFieldSet.empty
) extends scalapb.GeneratedMessage with scalapb.lenses.Updatable[ScalaPbOptions] with _root_.scalapb.ExtendableMessage[ScalaPbOptions] {
Expand Down Expand Up @@ -218,6 +221,10 @@ final case class ScalaPbOptions(
val __value = ignoreAllTransformations.get
__size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(26, __value)
};
if (getters.isDefined) {
val __value = getters.get
__size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(27, __value)
};
if (testOnlyNoJavaConversions.isDefined) {
val __value = testOnlyNoJavaConversions.get
__size += _root_.com.google.protobuf.CodedOutputStream.computeBoolSize(999, __value)
Expand Down Expand Up @@ -348,6 +355,10 @@ final case class ScalaPbOptions(
val __m = __v
_output__.writeBool(26, __m)
};
getters.foreach { __v =>
val __m = __v
_output__.writeBool(27, __m)
};
testOnlyNoJavaConversions.foreach { __v =>
val __m = __v
_output__.writeBool(999, __m)
Expand Down Expand Up @@ -440,6 +451,9 @@ final case class ScalaPbOptions(
def getIgnoreAllTransformations: _root_.scala.Boolean = ignoreAllTransformations.getOrElse(false)
def clearIgnoreAllTransformations: ScalaPbOptions = copy(ignoreAllTransformations = _root_.scala.None)
def withIgnoreAllTransformations(__v: _root_.scala.Boolean): ScalaPbOptions = copy(ignoreAllTransformations = Option(__v))
def getGetters: _root_.scala.Boolean = getters.getOrElse(true)
def clearGetters: ScalaPbOptions = copy(getters = _root_.scala.None)
def withGetters(__v: _root_.scala.Boolean): ScalaPbOptions = copy(getters = Option(__v))
def getTestOnlyNoJavaConversions: _root_.scala.Boolean = testOnlyNoJavaConversions.getOrElse(false)
def clearTestOnlyNoJavaConversions: ScalaPbOptions = copy(testOnlyNoJavaConversions = _root_.scala.None)
def withTestOnlyNoJavaConversions(__v: _root_.scala.Boolean): ScalaPbOptions = copy(testOnlyNoJavaConversions = Option(__v))
Expand Down Expand Up @@ -473,6 +487,7 @@ final case class ScalaPbOptions(
case 24 => preprocessors
case 25 => fieldTransformations
case 26 => ignoreAllTransformations.orNull
case 27 => getters.orNull
case 999 => testOnlyNoJavaConversions.orNull
}
}
Expand Down Expand Up @@ -505,6 +520,7 @@ final case class ScalaPbOptions(
case 24 => _root_.scalapb.descriptors.PRepeated(preprocessors.iterator.map(_root_.scalapb.descriptors.PString(_)).toVector)
case 25 => _root_.scalapb.descriptors.PRepeated(fieldTransformations.iterator.map(_.toPMessage).toVector)
case 26 => ignoreAllTransformations.map(_root_.scalapb.descriptors.PBoolean(_)).getOrElse(_root_.scalapb.descriptors.PEmpty)
case 27 => getters.map(_root_.scalapb.descriptors.PBoolean(_)).getOrElse(_root_.scalapb.descriptors.PEmpty)
case 999 => testOnlyNoJavaConversions.map(_root_.scalapb.descriptors.PBoolean(_)).getOrElse(_root_.scalapb.descriptors.PEmpty)
}
}
Expand Down Expand Up @@ -542,6 +558,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
val __preprocessors: _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String] = new _root_.scala.collection.immutable.VectorBuilder[_root_.scala.Predef.String]
val __fieldTransformations: _root_.scala.collection.immutable.VectorBuilder[scalapb.options.FieldTransformation] = new _root_.scala.collection.immutable.VectorBuilder[scalapb.options.FieldTransformation]
var __ignoreAllTransformations: _root_.scala.Option[_root_.scala.Boolean] = _root_.scala.None
var __getters: _root_.scala.Option[_root_.scala.Boolean] = _root_.scala.None
var __testOnlyNoJavaConversions: _root_.scala.Option[_root_.scala.Boolean] = _root_.scala.None
var `_unknownFields__`: _root_.scalapb.UnknownFieldSet.Builder = null
var _done__ = false
Expand Down Expand Up @@ -601,6 +618,8 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
__fieldTransformations += _root_.scalapb.LiteParser.readMessage[scalapb.options.FieldTransformation](_input__)
case 208 =>
__ignoreAllTransformations = Option(_input__.readBool())
case 216 =>
__getters = Option(_input__.readBool())
case 7992 =>
__testOnlyNoJavaConversions = Option(_input__.readBool())
case tag =>
Expand Down Expand Up @@ -637,6 +656,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
preprocessors = __preprocessors.result(),
fieldTransformations = __fieldTransformations.result(),
ignoreAllTransformations = __ignoreAllTransformations,
getters = __getters,
testOnlyNoJavaConversions = __testOnlyNoJavaConversions,
unknownFields = if (_unknownFields__ == null) _root_.scalapb.UnknownFieldSet.empty else _unknownFields__.result()
)
Expand Down Expand Up @@ -671,6 +691,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
preprocessors = __fieldsMap.get(scalaDescriptor.findFieldByNumber(24).get).map(_.as[_root_.scala.Seq[_root_.scala.Predef.String]]).getOrElse(_root_.scala.Seq.empty),
fieldTransformations = __fieldsMap.get(scalaDescriptor.findFieldByNumber(25).get).map(_.as[_root_.scala.Seq[scalapb.options.FieldTransformation]]).getOrElse(_root_.scala.Seq.empty),
ignoreAllTransformations = __fieldsMap.get(scalaDescriptor.findFieldByNumber(26).get).flatMap(_.as[_root_.scala.Option[_root_.scala.Boolean]]),
getters = __fieldsMap.get(scalaDescriptor.findFieldByNumber(27).get).flatMap(_.as[_root_.scala.Option[_root_.scala.Boolean]]),
testOnlyNoJavaConversions = __fieldsMap.get(scalaDescriptor.findFieldByNumber(999).get).flatMap(_.as[_root_.scala.Option[_root_.scala.Boolean]])
)
case _ => throw new RuntimeException("Expected PMessage")
Expand Down Expand Up @@ -728,6 +749,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
preprocessors = _root_.scala.Seq.empty,
fieldTransformations = _root_.scala.Seq.empty,
ignoreAllTransformations = _root_.scala.None,
getters = _root_.scala.None,
testOnlyNoJavaConversions = _root_.scala.None
)
/** Whether to apply the options only to this file, or for the entire package (and its subpackages)
Expand Down Expand Up @@ -1453,6 +1475,8 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
def fieldTransformations: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Seq[scalapb.options.FieldTransformation]] = field(_.fieldTransformations)((c_, f_) => c_.copy(fieldTransformations = f_))
def ignoreAllTransformations: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getIgnoreAllTransformations)((c_, f_) => c_.copy(ignoreAllTransformations = Option(f_)))
def optionalIgnoreAllTransformations: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.ignoreAllTransformations)((c_, f_) => c_.copy(ignoreAllTransformations = f_))
def getters: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getGetters)((c_, f_) => c_.copy(getters = Option(f_)))
def optionalGetters: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.getters)((c_, f_) => c_.copy(getters = f_))
def testOnlyNoJavaConversions: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Boolean] = field(_.getTestOnlyNoJavaConversions)((c_, f_) => c_.copy(testOnlyNoJavaConversions = Option(f_)))
def optionalTestOnlyNoJavaConversions: _root_.scalapb.lenses.Lens[UpperPB, _root_.scala.Option[_root_.scala.Boolean]] = field(_.testOnlyNoJavaConversions)((c_, f_) => c_.copy(testOnlyNoJavaConversions = f_))
}
Expand Down Expand Up @@ -1482,6 +1506,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
final val PREPROCESSORS_FIELD_NUMBER = 24
final val FIELD_TRANSFORMATIONS_FIELD_NUMBER = 25
final val IGNORE_ALL_TRANSFORMATIONS_FIELD_NUMBER = 26
final val GETTERS_FIELD_NUMBER = 27
final val TEST_ONLY_NO_JAVA_CONVERSIONS_FIELD_NUMBER = 999
def of(
packageName: _root_.scala.Option[_root_.scala.Predef.String],
Expand Down Expand Up @@ -1510,6 +1535,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
preprocessors: _root_.scala.Seq[_root_.scala.Predef.String],
fieldTransformations: _root_.scala.Seq[scalapb.options.FieldTransformation],
ignoreAllTransformations: _root_.scala.Option[_root_.scala.Boolean],
getters: _root_.scala.Option[_root_.scala.Boolean],
testOnlyNoJavaConversions: _root_.scala.Option[_root_.scala.Boolean]
): _root_.scalapb.options.ScalaPbOptions = _root_.scalapb.options.ScalaPbOptions(
packageName,
Expand Down Expand Up @@ -1538,6 +1564,7 @@ object ScalaPbOptions extends scalapb.GeneratedMessageCompanion[scalapb.options.
preprocessors,
fieldTransformations,
ignoreAllTransformations,
getters,
testOnlyNoJavaConversions
)
// @@protoc_insertion_point(GeneratedMessageCompanion[scalapb.ScalaPbOptions])
Expand Down
Loading

0 comments on commit 3590047

Please sign in to comment.