From d74e2945f786ede926cadc74396013b39130e721 Mon Sep 17 00:00:00 2001 From: razvanalex Date: Wed, 21 Jan 2026 02:06:07 +0200 Subject: [PATCH] [C++] Check for case insensitive keywords (#8420) * chore(idl): Check for case insensitive keywords Most languages are not affected by this change. In PHP, some names such as Bool cannot be used because it is a reserved keyword for to the bool data type. The field `keywords_casing` in the configs enables checking all characters in lowercase against every keyword. This should be safe as flatbuffers does not allow non-ASCII characters in its grammar. * chore: Fix formatting to follow google's coding style for enums * chore: Extract convert case to lower when CaseInsensitive --------- Co-authored-by: Justin Davis Co-authored-by: Derek Bailey --- include/codegen/namer.h | 18 +++++++++++++++++- include/codegen/python.h | 2 ++ src/bfbs_gen_lua.cpp | 1 + src/bfbs_gen_nim.cpp | 1 + src/idl_gen_dart.cpp | 1 + src/idl_gen_go.cpp | 1 + src/idl_gen_java.cpp | 1 + src/idl_gen_kotlin.cpp | 1 + src/idl_gen_kotlin_kmp.cpp | 1 + src/idl_gen_rust.cpp | 1 + src/idl_gen_swift.cpp | 1 + src/idl_gen_ts.cpp | 1 + 12 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/codegen/namer.h b/include/codegen/namer.h index e99bf744c..d447b565f 100644 --- a/include/codegen/namer.h +++ b/include/codegen/namer.h @@ -91,6 +91,14 @@ class Namer { std::string keyword_prefix; // Suffix used to escape keywords. It is usually "_". std::string keyword_suffix; + // The casing used for keywords when escaping. For most languages, keywords + // are case sensitive. PHP is an instance where some keywords are case + // insensitive. + enum class KeywordsCasing { + CaseSensitive, + CaseInsensitive, + }; + KeywordsCasing keywords_casing; // Files. @@ -204,8 +212,16 @@ class Namer { return result; } + virtual std::string NormalizeKeywordCase(const std::string& name) const { + if (config_.keywords_casing == Config::KeywordsCasing::CaseInsensitive) { + return ConvertCase(name, Case::kAllLower); + } else { + return name; + } + } + virtual std::string EscapeKeyword(const std::string& name) const { - if (keywords_.find(name) == keywords_.end()) { + if (keywords_.find(NormalizeKeywordCase(name)) == keywords_.end()) { return name; } else { return config_.keyword_prefix + name + config_.keyword_suffix; diff --git a/include/codegen/python.h b/include/codegen/python.h index cc6c241f2..a0a1ba81b 100644 --- a/include/codegen/python.h +++ b/include/codegen/python.h @@ -26,6 +26,7 @@ static const Namer::Config kConfig = { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", @@ -49,6 +50,7 @@ static const Namer::Config kStubConfig = { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/bfbs_gen_lua.cpp b/src/bfbs_gen_lua.cpp index f21892953..4507fe6d6 100644 --- a/src/bfbs_gen_lua.cpp +++ b/src/bfbs_gen_lua.cpp @@ -61,6 +61,7 @@ Namer::Config LuaDefaultConfig() { /*object_suffix=*/"", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/bfbs_gen_nim.cpp b/src/bfbs_gen_nim.cpp index d5ec2bd34..ec33e7487 100644 --- a/src/bfbs_gen_nim.cpp +++ b/src/bfbs_gen_nim.cpp @@ -70,6 +70,7 @@ Namer::Config NimDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/idl_gen_dart.cpp b/src/idl_gen_dart.cpp index 589e5d91f..e55c46602 100644 --- a/src/idl_gen_dart.cpp +++ b/src/idl_gen_dart.cpp @@ -48,6 +48,7 @@ static Namer::Config DartDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"$", /*keyword_suffix=*/"", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 9e743dd2d..a4a734588 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -75,6 +75,7 @@ static Namer::Config GoDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/idl_gen_java.cpp b/src/idl_gen_java.cpp index 5469286df..130751a74 100644 --- a/src/idl_gen_java.cpp +++ b/src/idl_gen_java.cpp @@ -46,6 +46,7 @@ static Namer::Config JavaDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/idl_gen_kotlin.cpp b/src/idl_gen_kotlin.cpp index 3a066d681..e9a83c696 100644 --- a/src/idl_gen_kotlin.cpp +++ b/src/idl_gen_kotlin.cpp @@ -64,6 +64,7 @@ static Namer::Config KotlinDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/idl_gen_kotlin_kmp.cpp b/src/idl_gen_kotlin_kmp.cpp index 571d452f0..b9111eda9 100644 --- a/src/idl_gen_kotlin_kmp.cpp +++ b/src/idl_gen_kotlin_kmp.cpp @@ -62,6 +62,7 @@ static Namer::Config KotlinDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"E", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kUpperCamel, /*directories=*/Case::kLowerCamel, /*output_path=*/"", diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 72d391e4b..d198a0723 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -49,6 +49,7 @@ static Namer::Config RustDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kSnake, /*directories=*/Case::kSnake, /*output_path=*/"", diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp index 63662b7fe..7d3a00d6c 100644 --- a/src/idl_gen_swift.cpp +++ b/src/idl_gen_swift.cpp @@ -47,6 +47,7 @@ static Namer::Config SwiftDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kKeep, /*directories=*/Case::kKeep, /*output_path=*/"", diff --git a/src/idl_gen_ts.cpp b/src/idl_gen_ts.cpp index aa05c23ab..14f366a83 100644 --- a/src/idl_gen_ts.cpp +++ b/src/idl_gen_ts.cpp @@ -67,6 +67,7 @@ Namer::Config TypeScriptDefaultConfig() { /*object_suffix=*/"T", /*keyword_prefix=*/"", /*keyword_suffix=*/"_", + /*keywords_casing=*/Namer::Config::KeywordsCasing::CaseSensitive, /*filenames=*/Case::kDasher, /*directories=*/Case::kDasher, /*output_path=*/"",