Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
86 changes: 86 additions & 0 deletions php/tests/GeneratedClassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,92 @@ public function testDeprecatedInt32Field()
$this->assertSame(4, $deprecationCount);
}

public function testDeprecatedFieldGetterDoesNotThrowWarning()
{
// temporarily change error handler to capture the deprecated errors
$deprecationCount = 0;
set_error_handler(function ($errno, $errstr) use (&$deprecationCount) {
if (false !== strpos($errstr, ' is deprecated.')) {
$deprecationCount++;
}
}, E_USER_DEPRECATED);

// does not throw warning
$message = new TestMessage();
$message->getDeprecatedInt32();
$message->getDeprecatedOptionalInt32();
$message->getDeprecatedInt32ValueUnwrapped(); // wrapped field
$message->getDeprecatedInt32Value(); // wrapped field
$message->getDeprecatedOneofInt32(); // oneof field
$message->getDeprecatedOneof(); // oneof field
$message->getDeprecatedRepeatedInt32(); // repeated field
$message->getDeprecatedMapInt32Int32(); // map field
$message->getDeprecatedAny(); // any field
$message->getDeprecatedMessage(); // message field
$message->getDeprecatedEnum(); // enum field

restore_error_handler();

$this->assertEquals(0, $deprecationCount);
}

public function testDeprecatedFieldGetterThrowsWarningWithValue()
{
$message = new TestMessage([
'deprecated_int32' => 1,
'deprecated_optional_int32' => 1,
'deprecated_int32_value' => new \Google\Protobuf\Int32Value(['value' => 1]),
'deprecated_oneof_int32' => 1,
'deprecated_repeated_int32' => [1],
'deprecated_map_int32_int32' => [1 => 1],
'deprecated_any' => new \Google\Protobuf\Any(['type_url' => 'foo', 'value' => 'bar']),
'deprecated_message' => new TestMessage(),
'deprecated_enum' => 1,
]);

// temporarily change error handler to capture the deprecated errors
$deprecationCount = 0;
set_error_handler(function ($errno, $errstr) use (&$deprecationCount) {
if (false !== strpos($errstr, ' is deprecated.')) {
$deprecationCount++;
}
}, E_USER_DEPRECATED);

$message->getDeprecatedInt32();
$message->getDeprecatedOptionalInt32();
$message->getDeprecatedInt32ValueUnwrapped(); // wrapped field unwrapped
$message->getDeprecatedInt32Value(); // wrapped field
$message->getDeprecatedOneofInt32(); // oneof field
$message->getDeprecatedRepeatedInt32(); // repeated field
$message->getDeprecatedMapInt32Int32(); // map field
$message->getDeprecatedAny(); // any field
$message->getDeprecatedMessage(); // message field
$message->getDeprecatedEnum(); // enum field

// oneof field (should never warn)
$message->getDeprecatedOneof();

restore_error_handler();

$this->assertEquals(10, $deprecationCount);
}

public function testDeprecatedFieldWarningsOnSerialize()
{
set_error_handler(function ($errno, $errstr) {
if (false !== strpos($errstr, ' is deprecated.')) {
throw new \Exception($errstr);
}
}, E_USER_DEPRECATED);

$message = new TestMessage();
$message->serializeToJsonString();

restore_error_handler();

$this->assertTrue(true, 'No deprecation warning on serialize');
}

#########################################################
# Test optional int32 field.
#########################################################
Expand Down
20 changes: 19 additions & 1 deletion php/tests/proto/test.proto
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,25 @@ message TestMessage {
map<string, google.protobuf.Struct> map_string_struct = 124;

// deprecated field
int32 deprecated_optional_int32 = 125 [deprecated=true];
int32 deprecated_int32 = 125 [deprecated=true];
// deprecated optional field
optional int32 deprecated_optional_int32 = 126 [deprecated=true];
// deprecated wrapped field
google.protobuf.Int32Value deprecated_int32_value = 127 [deprecated=true];
// deprecated oneof
oneof deprecated_oneof {
int32 deprecated_oneof_int32 = 128 [deprecated=true];
}
// deprecated repeated field
repeated int32 deprecated_repeated_int32 = 129 [deprecated = true];
// deprecated map
map<int32, int32> deprecated_map_int32_int32 = 130 [deprecated = true];
// deprecated any
google.protobuf.Any deprecated_any = 131 [deprecated = true];
// deprecated message
TestMessage deprecated_message = 132 [deprecated = true];
// deprecated enum
NestedEnum deprecated_enum = 133 [deprecated = true];
}

enum TestEnum {
Expand Down
49 changes: 40 additions & 9 deletions src/google/protobuf/compiler/php/php_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,20 @@ std::string DefaultForField(const FieldDescriptor* field) {
}
}

std::string DeprecatedConditionalForField(const FieldDescriptor* field) {
if (field->is_repeated()) {
return absl::StrCat("$this->", field->name(), "->count() !== 0");
}
if (field->real_containing_oneof() != nullptr) {
return absl::StrCat("$this->hasOneof(", field->number(), ")");
}
if (field->has_presence()) {
return absl::StrCat("isset($this->", field->name(), ")");
}
return absl::StrCat("$this->", field->name(), " !== ",
field->has_presence() ? "null" : DefaultForField(field));
}

std::string GeneratedMetadataFileName(const FileDescriptor* file,
const Options& options) {
absl::string_view proto_file = file->name();
Expand Down Expand Up @@ -574,6 +588,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
? absl::StrCat("@trigger_error('", field->name(),
" is deprecated.', E_USER_DEPRECATED);\n ")
: "";
std::string deprecation_trigger_with_conditional =
(field->options().deprecated())
? absl::StrCat("if (" + DeprecatedConditionalForField(field),
") {\n ", deprecation_trigger,
"}\n ")
: "";

// Emit getter.
if (oneof != nullptr) {
Expand All @@ -584,7 +604,7 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
"}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "number",
IntToString(field->number()), "deprecation_trigger",
deprecation_trigger);
deprecation_trigger_with_conditional);
} else if (field->has_presence() && !field->message_type()) {
printer->Print(
"public function get^camel_name^()\n"
Expand All @@ -594,15 +614,16 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
"}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "name",
field->name(), "default_value", DefaultForField(field),
"deprecation_trigger", deprecation_trigger);
"deprecation_trigger", deprecation_trigger_with_conditional);
} else {
printer->Print(
"public function get^camel_name^()\n"
"{\n"
" ^deprecation_trigger^return $this->^name^;\n"
"}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "name",
field->name(), "deprecation_trigger", deprecation_trigger);
field->name(), "deprecation_trigger",
deprecation_trigger_with_conditional);
}

// Emit hazzers/clear.
Expand All @@ -614,20 +635,22 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
"}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "number",
IntToString(field->number()), "deprecation_trigger",
deprecation_trigger);
deprecation_trigger_with_conditional);
} else if (field->has_presence()) {
printer->Print(
"public function has^camel_name^()\n"
"{\n"
" ^deprecation_trigger^return isset($this->^name^);\n"
"}\n\n"
" ^deprecation_trigger_with_conditional^return isset($this->^name^);"
"\n}\n\n"
"public function clear^camel_name^()\n"
"{\n"
" ^deprecation_trigger^unset($this->^name^);\n"
"}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "name",
field->name(), "default_value", DefaultForField(field),
"deprecation_trigger", deprecation_trigger);
"deprecation_trigger", deprecation_trigger,
"deprecation_trigger_with_conditional",
deprecation_trigger_with_conditional);
}

// For wrapper types, generate an additional getXXXUnwrapped getter
Expand All @@ -642,7 +665,8 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
"$this->readWrapperValue(\"^field_name^\");\n"
"}\n\n",
"camel_name", UnderscoresToCamelCase(field->name(), true), "field_name",
field->name(), "deprecation_trigger", deprecation_trigger);
field->name(), "deprecation_trigger",
deprecation_trigger_with_conditional);
}

// Generate setter.
Expand All @@ -654,7 +678,8 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,

Indent(printer);

if (field->options().deprecated()) {
if (field->options().deprecated() && !field->is_map() &&
!field->is_repeated()) {
printer->Print("^deprecation_trigger^", "deprecation_trigger",
deprecation_trigger);
}
Expand Down Expand Up @@ -712,6 +737,12 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options,
UnderscoresToCamelCase(field->cpp_type_name(), true));
}

if (field->options().deprecated() && (field->is_map() ||
field->is_repeated())) {
printer->Print("if ($arr->count() !== 0) {\n ^deprecation_trigger^}\n",
"deprecation_trigger", deprecation_trigger);
}

if (oneof != nullptr) {
printer->Print("$this->writeOneof(^number^, $var);\n", "number",
IntToString(field->number()));
Expand Down