Skip to content

Commit cf3a6f5

Browse files
habermancopybara-github
authored andcommitted
Enabled editions support for upb generated code.
This required enabling the feature in the code generator and fixing a few edge cases around label and type. Also added tests to verify the special cases, and to verify that required fields work as expected. PiperOrigin-RevId: 580263087
1 parent bb40d91 commit cf3a6f5

File tree

14 files changed

+277
-57
lines changed

14 files changed

+277
-57
lines changed

src/google/protobuf/compiler/allowlists/editions.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ static constexpr auto kEarlyEditionsFile = internal::MakeAllowlist(
2020
{
2121
// Intentionally left blank.
2222
"google/protobuf/",
23+
"upb/",
2324
},
2425
internal::AllowlistFlags::kMatchPrefix);
2526

upb/reflection/field_def.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,26 @@ upb_CType upb_FieldDef_CType(const upb_FieldDef* f) {
123123
UPB_UNREACHABLE();
124124
}
125125

126-
upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { return f->type_; }
126+
upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) {
127+
// TODO: remove once we can deprecate kUpb_FieldType_Group.
128+
if (f->type_ == kUpb_FieldType_Message &&
129+
UPB_DESC(FeatureSet_message_encoding)(f->resolved_features) ==
130+
UPB_DESC(FeatureSet_DELIMITED)) {
131+
return kUpb_FieldType_Group;
132+
}
133+
return f->type_;
134+
}
127135

128136
uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; }
129137

130-
upb_Label upb_FieldDef_Label(const upb_FieldDef* f) { return f->label_; }
138+
upb_Label upb_FieldDef_Label(const upb_FieldDef* f) {
139+
// TODO: remove once we can deprecate kUpb_Label_Required.
140+
if (UPB_DESC(FeatureSet_field_presence)(f->resolved_features) ==
141+
UPB_DESC(FeatureSet_LEGACY_REQUIRED)) {
142+
return kUpb_Label_Required;
143+
}
144+
return f->label_;
145+
}
131146

132147
uint32_t upb_FieldDef_Number(const upb_FieldDef* f) { return f->number_; }
133148

upb/test/BUILD

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,24 @@ upb_c_proto_library(
8484
deps = [":test_proto"],
8585
)
8686

87+
proto_library(
88+
name = "editions_test_proto",
89+
testonly = 1,
90+
srcs = ["editions_test.proto"],
91+
)
92+
93+
upb_c_proto_library(
94+
name = "editions_test_upb_c_proto",
95+
testonly = 1,
96+
deps = [":editions_test_proto"],
97+
)
98+
99+
upb_proto_reflection_library(
100+
name = "editions_test_upb_proto_reflection",
101+
testonly = 1,
102+
deps = [":editions_test_proto"],
103+
)
104+
87105
proto_library(
88106
name = "test_cpp_proto",
89107
srcs = ["test_cpp.proto"],
@@ -166,6 +184,20 @@ cc_test(
166184
],
167185
)
168186

187+
cc_test(
188+
name = "editions_test",
189+
srcs = ["editions_test.cc"],
190+
copts = UPB_DEFAULT_CPPOPTS,
191+
deps = [
192+
":editions_test_upb_c_proto",
193+
":editions_test_upb_proto_reflection",
194+
"@com_google_googletest//:gtest_main",
195+
"//upb:base",
196+
"//upb:mem",
197+
"//upb:reflection",
198+
],
199+
)
200+
169201
cc_test(
170202
name = "test_cpp",
171203
srcs = ["test_cpp.cc"],

upb/test/editions_test.cc

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Protocol Buffers - Google's data interchange format
2+
// Copyright 2023 Google LLC. All rights reserved.
3+
//
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file or at
6+
// https://developers.google.com/open-source/licenses/bsd
7+
8+
#include <gtest/gtest.h>
9+
#include "upb/base/descriptor_constants.h"
10+
#include "upb/mem/arena.hpp"
11+
#include "upb/reflection/def.hpp"
12+
#include "upb/test/editions_test.upb.h"
13+
#include "upb/test/editions_test.upbdefs.h"
14+
15+
TEST(EditionsTest, PlainField) {
16+
upb::DefPool defpool;
17+
upb::MessageDefPtr md(upb_test_2023_EditionsMessage_getmsgdef(defpool.ptr()));
18+
upb::FieldDefPtr f(md.FindFieldByName("plain_field"));
19+
EXPECT_TRUE(f.has_presence());
20+
}
21+
22+
TEST(EditionsTest, ImplicitPresenceField) {
23+
upb::DefPool defpool;
24+
upb::MessageDefPtr md(upb_test_2023_EditionsMessage_getmsgdef(defpool.ptr()));
25+
upb::FieldDefPtr f(md.FindFieldByName("implicit_presence_field"));
26+
EXPECT_FALSE(f.has_presence());
27+
}
28+
29+
TEST(EditionsTest, DelimitedField) {
30+
upb::DefPool defpool;
31+
upb::MessageDefPtr md(upb_test_2023_EditionsMessage_getmsgdef(defpool.ptr()));
32+
upb::FieldDefPtr f(md.FindFieldByName("delimited_field"));
33+
EXPECT_EQ(kUpb_FieldType_Group, f.type());
34+
}
35+
36+
TEST(EditionsTest, RequiredField) {
37+
upb::DefPool defpool;
38+
upb::MessageDefPtr md(upb_test_2023_EditionsMessage_getmsgdef(defpool.ptr()));
39+
upb::FieldDefPtr f(md.FindFieldByName("required_field"));
40+
EXPECT_EQ(kUpb_Label_Required, f.label());
41+
}
42+
43+
TEST(EditionsTest, ClosedEnum) {
44+
upb::DefPool defpool;
45+
upb::MessageDefPtr md(upb_test_2023_EditionsMessage_getmsgdef(defpool.ptr()));
46+
upb::FieldDefPtr f(md.FindFieldByName("enum_field"));
47+
ASSERT_TRUE(f.enum_subdef().is_closed());
48+
}
49+
50+
TEST(EditionsTest, PackedField) {
51+
upb::DefPool defpool;
52+
upb::MessageDefPtr md(upb_test_2023_EditionsMessage_getmsgdef(defpool.ptr()));
53+
upb::FieldDefPtr f(md.FindFieldByName("unpacked_field"));
54+
ASSERT_FALSE(f.packed());
55+
}
56+
57+
TEST(EditionsTest, ConstructProto) {
58+
// Doesn't do anything except construct the proto. This just verifies that
59+
// the generated code compiles successfully.
60+
upb::Arena arena;
61+
upb_test_2023_EditionsMessage_new(arena.ptr());
62+
}

upb/test/editions_test.proto

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Protocol Buffers - Google's data interchange format
2+
// Copyright 2023 Google LLC. All rights reserved.
3+
//
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file or at
6+
// https://developers.google.com/open-source/licenses/bsd
7+
8+
edition = "2023";
9+
10+
package upb.test_2023;
11+
12+
message EditionsMessage {
13+
int32 plain_field = 1;
14+
int32 implicit_presence_field = 2 [features.field_presence = IMPLICIT];
15+
int32 required_field = 3 [features.field_presence = LEGACY_REQUIRED];
16+
EditionsMessage delimited_field = 4 [features.message_encoding = DELIMITED];
17+
EditionsEnum enum_field = 5;
18+
repeated int32 unpacked_field = 6
19+
[features.repeated_field_encoding = EXPANDED];
20+
}
21+
22+
enum EditionsEnum {
23+
option features.enum_type = CLOSED;
24+
25+
ONE = 1;
26+
}

upb/util/BUILD

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,10 @@ cc_library(
106106

107107
proto_library(
108108
name = "required_fields_test_proto",
109-
srcs = ["required_fields_test.proto"],
109+
srcs = [
110+
"required_fields_editions_test.proto",
111+
"required_fields_test.proto",
112+
],
110113
)
111114

112115
upb_c_proto_library(
@@ -131,6 +134,7 @@ cc_test(
131134
"//upb:json",
132135
"//upb:mem",
133136
"//upb:reflection",
137+
"//upb:reflection_internal",
134138
"@com_google_absl//absl/strings",
135139
],
136140
)

upb/util/def_to_proto.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ static google_protobuf_FileDescriptorProto* filedef_toproto(upb_ToProto_Context*
511511

512512
if (upb_FileDef_Syntax(f) == kUpb_Syntax_Proto3) {
513513
google_protobuf_FileDescriptorProto_set_syntax(proto, strviewdup(ctx, "proto3"));
514+
} else if (upb_FileDef_Syntax(f) == kUpb_Syntax_Editions) {
515+
google_protobuf_FileDescriptorProto_set_syntax(proto, strviewdup(ctx, "editions"));
514516
}
515517

516518
size_t n;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Protocol Buffers - Google's data interchange format
2+
// Copyright 2023 Google LLC. All rights reserved.
3+
//
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file or at
6+
// https://developers.google.com/open-source/licenses/bsd
7+
8+
edition = "2023";
9+
10+
package upb_util_2023_test;
11+
12+
message EmptyMessage {}
13+
14+
message HasRequiredField {
15+
int32 required_int32 = 1 [features.field_presence = LEGACY_REQUIRED];
16+
}
17+
18+
message TestRequiredFields {
19+
EmptyMessage required_message = 1 [features.field_presence = LEGACY_REQUIRED];
20+
TestRequiredFields optional_message = 2;
21+
repeated HasRequiredField repeated_message = 3;
22+
map<int32, HasRequiredField> map_int32_message = 4;
23+
map<int64, HasRequiredField> map_int64_message = 5;
24+
map<uint32, HasRequiredField> map_uint32_message = 6;
25+
map<uint64, HasRequiredField> map_uint64_message = 7;
26+
map<bool, HasRequiredField> map_bool_message = 8;
27+
map<string, HasRequiredField> map_string_message = 9;
28+
}

0 commit comments

Comments
 (0)