Skip to content

Commit 1137de8

Browse files
aristidispmeta-codesync[bot]
authored andcommitted
Validate enum names matching enclosing type name
Summary: This adds validation for enum values, simiar to the existing logic for field names. It also adds extra-validation flags to eventually allow checks (for both conflicting field names and enum value names) to become errors. Reviewed By: Mizuchi Differential Revision: D94785494 fbshipit-source-id: 1460c41ab8b9ea2ed5ce5707b4272d78223ef49c
1 parent 2aa8d2b commit 1137de8

4 files changed

Lines changed: 82 additions & 7 deletions

File tree

third-party/thrift/src/thrift/compiler/compiler.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,16 @@ void printUsageTo(FILE* stream) {
217217
Ignore @thrift.AllowLegacyMissingUris when checking for
218218
missing URIs. Requires missing_uris=error.
219219
220+
field_name_matches_enclosing_type=none|warn|error
221+
Action to take when a field in a structured type has the
222+
same name as the enclosing type.
223+
Default: warn
224+
225+
enum_value_name_matches_enclosing_type=none|warn|error
226+
Action to take when an enum value has the same name as the
227+
enclosing enum type.
228+
Default: none
229+
220230
warn_on_redundant_custom_default_values
221231
DEPRECATED, prefer: redundant_custom_default_values=warn
222232
@@ -1049,6 +1059,19 @@ std::string parse_args(
10491059
continue;
10501060
}
10511061

1062+
if (maybe_parse_validation_level_flag(
1063+
/*flag=*/validator,
1064+
/*prefix=*/"field_name_matches_enclosing_type",
1065+
&sparams.field_name_matches_enclosing_type)) {
1066+
continue;
1067+
}
1068+
1069+
if (maybe_parse_validation_level_flag(
1070+
/*flag=*/validator,
1071+
/*prefix=*/"enum_value_name_matches_enclosing_type",
1072+
&sparams.enum_value_name_matches_enclosing_type)) {
1073+
continue;
1074+
}
10521075
} catch (const std::exception& e) {
10531076
fmt::print(
10541077
stderr,
@@ -1243,6 +1266,14 @@ void record_invocation_params(
12431266
sema_params_metric.add(
12441267
fmt::format(
12451268
"ignore_missing_uri_opt_out={}", sparams.ignore_missing_uri_opt_out));
1269+
sema_params_metric.add(
1270+
fmt::format(
1271+
"field_name_matches_enclosing_type={}",
1272+
fmt::underlying(sparams.field_name_matches_enclosing_type)));
1273+
sema_params_metric.add(
1274+
fmt::format(
1275+
"enum_value_name_matches_enclosing_type={}",
1276+
fmt::underlying(sparams.enum_value_name_matches_enclosing_type)));
12461277
sema_params_metric.add(
12471278
"warn_on_redundant_custom_default_values=" +
12481279
std::to_string(

third-party/thrift/src/thrift/compiler/sema/sema_context.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ struct sema_params {
198198
// If true, ignore @thrift.AllowLegacyMissingUris opt-out when checking for
199199
// missing URIs. Requires missing_uris to be set to error.
200200
bool ignore_missing_uri_opt_out = false;
201+
202+
// Action to take when a field in a structured type (struct, union, exception)
203+
// has the same name as the enclosing type.
204+
validation_level field_name_matches_enclosing_type = validation_level::warn;
205+
206+
// Action to take when an enum value has the same name as the enclosing enum
207+
// type.
208+
validation_level enum_value_name_matches_enclosing_type =
209+
validation_level::none;
201210
};
202211

203212
// An AST visitor context for semantic analysis. It combines diagnostics

third-party/thrift/src/thrift/compiler/sema/standard_validator.cc

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,22 @@ void validate_enum_value_uniqueness(sema_context& ctx, const t_enum& node) {
808808
}
809809
}
810810

811+
void validate_enum_value_name_not_enclosing_type(
812+
sema_context& ctx, const t_enum& node) {
813+
for (const t_enum_value& value : node.values()) {
814+
if (value.name() == node.name()) {
815+
ctx.report(
816+
value,
817+
validation_to_diagnostic_level(
818+
ctx.sema_parameters().enum_value_name_matches_enclosing_type),
819+
"Enum value `{}` has the same name as the enclosing type `{}`.",
820+
value.name(),
821+
node.name());
822+
return;
823+
}
824+
}
825+
}
826+
811827
void validate_enum_value(sema_context& ctx, const t_enum_value& node) {
812828
if (!node.has_value()) {
813829
ctx.error(
@@ -942,7 +958,10 @@ void validate_field_name(sema_context& ctx, const t_field& field) {
942958
} else {
943959
parent_structure = "struct";
944960
}
945-
ctx.warning(
961+
ctx.report(
962+
field,
963+
validation_to_diagnostic_level(
964+
ctx.sema_parameters().field_name_matches_enclosing_type),
946965
"Field '{}' has the same name as the containing {}.",
947966
field.name(),
948967
parent_structure);
@@ -2292,6 +2311,7 @@ ast_validator standard_validator() {
22922311

22932312
validator.add_enum_visitor(&validate_enum_value_name_uniqueness);
22942313
validator.add_enum_visitor(&validate_enum_value_uniqueness);
2314+
validator.add_enum_visitor(&validate_enum_value_name_not_enclosing_type);
22952315
validator.add_enum_visitor(&validate_reserved_ids_enum);
22962316
validator.add_enum_value_visitor(&validate_enum_value);
22972317

third-party/thrift/src/thrift/compiler/test/compiler_test.cc

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,22 +2624,37 @@ TEST(CompilerTest, alias_enum_in_external_const) {
26242624
check_compile(name_contents_map, "baz.thrift");
26252625
}
26262626

2627-
TEST(CompilerTest, same_named_field) {
2628-
check_compile(R"(
2627+
TEST(CompilerTest, same_named_field_error) {
2628+
check_compile(
2629+
R"(
26292630
package "facebook.com/thrift/test"
26302631
struct S {
26312632
1: i32 S;
2632-
# expected-warning@-1: Field 'S' has the same name as the containing struct.
2633+
# expected-error@-1: Field 'S' has the same name as the containing struct.
26332634
}
26342635
union U {
26352636
1: i32 U;
2636-
# expected-warning@-1: Field 'U' has the same name as the containing union.
2637+
# expected-error@-1: Field 'U' has the same name as the containing union.
26372638
}
26382639
exception E {
26392640
1: i32 E;
2640-
# expected-warning@-1: Field 'E' has the same name as the containing exception.
2641+
# expected-error@-1: Field 'E' has the same name as the containing exception.
26412642
}
2642-
)");
2643+
)",
2644+
{"--extra-validation", "field_name_matches_enclosing_type=error"});
2645+
}
2646+
2647+
TEST(CompilerTest, enum_value_name_matches_enclosing_type) {
2648+
check_compile(
2649+
R"(
2650+
package "facebook.com/thrift/test"
2651+
enum E {
2652+
E = 0,
2653+
# expected-warning@-1: Enum value `E` has the same name as the enclosing type `E`.
2654+
Other = 1,
2655+
}
2656+
)",
2657+
{"--extra-validation", "enum_value_name_matches_enclosing_type=warn"});
26432658
}
26442659

26452660
TEST(CompilerTest, cursor_serialization_adapter) {

0 commit comments

Comments
 (0)