Skip to content

Commit

Permalink
scrooge-generator: Add the ability to unset multiple fields at once
Browse files Browse the repository at this point in the history
Problem

Sometimes customers want to unset many parts of their struct.

Solution

Provide an API to do a lot of unsetting all at once.

JIRA Issues: CSL-12001

Differential Revision: https://phabricator.twitter.biz/D911135
  • Loading branch information
mosesn authored and jenkins committed Jul 11, 2022
1 parent a9a08a6 commit aef5029
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ New Features

* scrooge-generator: Add @.generated annotation to Swift generated code ``PHAB_ID=D879262``

* scrooge-generator: Provide a `$STRUCT#unsetFields` method to allow bulk unsets ``PHAB_ID=D911135``

* scrooge-generator: support thrift validations on nested fields that are struct, union, and
exception ``PHAB_ID=D911262``

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,18 @@ class AnotherException(
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): AnotherException = {
new AnotherException(
if (_fieldIds(1)) 0 else this.errorCode,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,18 @@ trait CollectionId
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): CollectionId = {
new Immutable(
if (_fieldIds(1)) 0L else this.collectionLongId,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,18 @@ class OverCapacityException(
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): OverCapacityException = {
new OverCapacityException(
if (_fieldIds(1)) 0 else this.chillTimeSeconds,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,19 @@ trait Recursive
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): Recursive = {
new Immutable(
if (_fieldIds(1)) 0L else this.id,
if (_fieldIds(2)) _root_.scala.None else this.recRequest,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,33 @@ trait Request
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): Request = {
new Immutable(
if (_fieldIds(1)) _root_.scala.collection.immutable.Nil else this.aList,
if (_fieldIds(2)) _root_.scala.collection.immutable.Set.empty else this.aSet,
if (_fieldIds(3)) _root_.scala.collection.immutable.Map.empty else this.aMap,
if (_fieldIds(4)) _root_.scala.None else this.aRequest,
if (_fieldIds(5)) _root_.scala.collection.immutable.Nil else this.subRequests,
if (_fieldIds(6)) "the_default" else this._default,
if (_fieldIds(7)) _root_.scala.None else this.noComment,
if (_fieldIds(8)) _root_.scala.None else this.doubleSlashComment,
if (_fieldIds(9)) _root_.scala.None else this.hashtagComment,
if (_fieldIds(10)) _root_.scala.None else this.singleAsteriskComment,
if (_fieldIds(11)) _root_.scala.None else this.docStringComment,
if (_fieldIds(12)) _root_.scala.None else this.recRequest,
if (_fieldIds(13)) null else this.requiredField,
if (_fieldIds(14)) _root_.scala.None else this.constructionRequiredField,
if (_fieldIds(15)) _root_.scala.None else this.anInt8,
if (_fieldIds(16)) _root_.scala.None else this.aBinaryField,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,18 @@ class RequestException(
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): RequestException = {
new RequestException(
if (_fieldIds(1)) null else this.message,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,19 @@ trait Response
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): Response = {
new Immutable(
if (_fieldIds(1)) 0 else this.statusCode,
if (_fieldIds(2)) null else this.responseUnion,
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,34 @@ class ImmutableStructSpec extends Spec {
)
Xtruct.Immutable.metaData.fields.map(_.name).toSet must be(expectedFieldNames)
}

"unset non-optional field" in {
val xtruct = Xtruct(
"string_thing",
10.toByte,
100,
1000L
)
xtruct.unsetField(4) must be(Xtruct("string_thing", 0.toByte, 100, 1000L))
}

"unset optional field" in {
val boolTest = OptionalInt(
"my_name",
Some(32)
)
boolTest.unsetField(2) must be(OptionalInt("my_name", None))
}

"unset fields" in {
val xtruct = Xtruct(
"string_thing",
10.toByte,
100,
1000L
)

xtruct.unsetFields(Set(1, 4, 9)) must be(Xtruct(null, 0.toByte, 0, 1000L))
}
}
}
14 changes: 14 additions & 0 deletions scrooge-generator/src/main/resources/scalagen/struct.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,20 @@ class {{StructName}}(
)
}

/**
* If the specified fields are optional, they are set to None. Otherwise, if the fields are
* known, they are reverted to their default values; if the fields are unknown, they are removed
* from the passthroughFields map, if present.
*/
def unsetFields(_fieldIds: Set[Short]): {{StructName}} = {
new {{InstanceClassName}}(
{{#fields}}
if (_fieldIds({{id}})) {{#optional}}_root_.scala.None{{/optional}}{{^optional}}{{defaultReadValue}}{{/optional}} else this.{{fieldName}},
{{/fields}}
_passthroughFields -- _fieldIds
)
}

/**
* If the specified field is optional, it is set to None. Otherwise, if the field is
* known, it is reverted to its default value; if the field is unknown, it is removed
Expand Down

0 comments on commit aef5029

Please sign in to comment.