Skip to content

Commit 124a84e

Browse files
C#: When adjusting parameter names matching keywords, also adjust those names in the function comment if any.
1 parent 063dc2e commit 124a84e

12 files changed

Lines changed: 151 additions & 9 deletions

File tree

src/generators/csharp/generator.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ namespace mrbind::CSharp
8888
}
8989
}
9090

91-
bool AdjustIfMatchesCSharpKeyword(std::string &str)
91+
bool AdjustIfMatchesCSharpKeyword(std::string &str, std::string *also_adjust)
9292
{
9393
static const std::unordered_set<std::string> csharp_keywords = {
9494
// Those are from here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/
@@ -174,7 +174,35 @@ namespace mrbind::CSharp
174174

175175
if (csharp_keywords.contains(str))
176176
{
177-
str += '_';
177+
std::string new_str = str + '_';
178+
179+
if (also_adjust)
180+
{
181+
auto HandleOccurence = [&](const std::string &prefix, const std::string &suffix)
182+
{
183+
*also_adjust = Strings::Replace(*also_adjust, prefix + str + suffix, prefix + new_str + suffix);
184+
};
185+
186+
// Just some quotes.
187+
HandleOccurence("`", "`");
188+
HandleOccurence("'", "'");
189+
HandleOccurence("\"", "\"");
190+
191+
// Doxygen.
192+
for (std::string symbol : {"@", "\\"})
193+
{
194+
// Parameter descriptions.
195+
HandleOccurence(symbol + "param ", " ");
196+
197+
// Single words in inline code blocks.
198+
// `c` and `p` do the same thing.
199+
HandleOccurence(symbol + "c ", " ");
200+
HandleOccurence(symbol + "p ", " ");
201+
}
202+
}
203+
204+
str = std::move(new_str);
205+
178206
return true;
179207
}
180208

@@ -8232,25 +8260,23 @@ namespace mrbind::CSharp
82328260
}
82338261

82348262
{ // Adjust parameter names to not be C# keywords.
8235-
8236-
8237-
static constexpr auto AdjustParam = [](CInterop::FuncParam &param)
8263+
static constexpr auto AdjustParam = [](CInterop::FuncParam &param, std::string &comment)
82388264
{
82398265
if (param.name)
82408266
{
8241-
if (AdjustIfMatchesCSharpKeyword(*param.name))
8267+
if (AdjustIfMatchesCSharpKeyword(*param.name, &comment))
82428268
param.name_or_placeholder = *param.name;
82438269
}
82448270
else
82458271
{
8246-
AdjustIfMatchesCSharpKeyword(param.name_or_placeholder); // Just in case?
8272+
AdjustIfMatchesCSharpKeyword(param.name_or_placeholder, &comment); // Just in case?
82478273
}
82488274
};
82498275

82508276
static constexpr auto AdjustFuncLike = [](CInterop::BasicFuncLike &func)
82518277
{
82528278
for (auto &param : func.params)
8253-
AdjustParam(param);
8279+
AdjustParam(param, func.comment.c_style);
82548280
};
82558281

82568282
// Free functions.

src/generators/csharp/generator.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ namespace mrbind::CSharp
101101

102102
// If `str` matches one of C# keywords, appends `_` to it to avoid collisions.
103103
// Returns true if the adjustment has been made.
104-
bool AdjustIfMatchesCSharpKeyword(std::string &str);
104+
// If `also_adjust` is specified and an adjustment was made, we also apply this replacement to occurences of the offending string in `*also_adjust`,
105+
// but only in specific contexts, to avoid confusing it with plain English words. Those contexts include different kinds of quotes,
106+
// `\param ...` doxygen parameter names, etc.
107+
bool AdjustIfMatchesCSharpKeyword(std::string &str, std::string *also_adjust = nullptr);
105108

106109
// You can call this on the result of the `...ToCSharpIdentifier()` functions above, to make the first letter of the result lowercase.
107110
// Also calls `AdjustIfMatchesCSharpKeyword()` to avoid keyword collisions.

test/input/MR/test_csharp.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ namespace MR::CSharp
8282
inline const std::string test_constness_str(const std::string, const std::string = "42") {return "43";}
8383
#pragma clang diagnostic pop
8484

85+
// Test how we adjust keywords in parameter names.
86+
// \param params blah
87+
// @param params blah
88+
// `params` 'params' "params" params huhparams paramshuh \p params \c params @p params @c params \A params @A params
89+
// In this comment, only quoted and `\param ...` uses are adjusted, and not standalone occurences of the word (even if it's a separate word, let alone if it's just a part of a word).
90+
// `\c ...` and `\p ...` are handled, but unknown tags like `\A ...` are not.
91+
// <param name="params">This is also handled, naturally, because we handle quotes.</param>
92+
inline void test_keyword_in_param_name(int params) {(void)params;}
93+
8594

8695
/// Enum comment.
8796
enum class E1

test/output_c/include/MR/test_csharp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,16 @@ MR_C_API int MR_CSharp_test_constness_int(int _1, const int *_2);
867867
/// Never returns null. Returns an instance allocated on the heap! Must call `MR_C_std_string_Destroy()` to free it when you're done using it.
868868
MR_C_API MR_C_std_string *MR_CSharp_test_constness_str(const char *_1, const char *_1_end, const char *_2, const char *_2_end);
869869

870+
// Test how we adjust keywords in parameter names.
871+
// \param params blah
872+
// @param params blah
873+
// `params` 'params' "params" params huhparams paramshuh \p params \c params @p params @c params \A params @A params
874+
// In this comment, only quoted and `\param ...` uses are adjusted, and not standalone occurences of the word (even if it's a separate word, let alone if it's just a part of a word).
875+
// `\c ...` and `\p ...` are handled, but unknown tags like `\A ...` are not.
876+
// <param name="params">This is also handled, naturally, because we handle quotes.</param>
877+
/// Generated from function `MR::CSharp::test_keyword_in_param_name`.
878+
MR_C_API void MR_CSharp_test_keyword_in_param_name(int params);
879+
870880
/// Generated from function `MR::CSharp::test_enum`.
871881
/// Parameter `b` has a default argument: `E1::b`, pass a null pointer to use it.
872882
MR_C_API MR_CSharp_E1 MR_CSharp_test_enum_MR_CSharp_E1(MR_CSharp_E1 a, const MR_CSharp_E1 *b);

test/output_c/source/MR/test_csharp.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,15 @@ MR_C_std_string *MR_CSharp_test_constness_str(const char *_1, const char *_1_end
284284
) // MRBINDC_TRY
285285
}
286286

287+
void MR_CSharp_test_keyword_in_param_name(int params)
288+
{
289+
MRBINDC_TRY(
290+
::MR::CSharp::test_keyword_in_param_name(
291+
params
292+
);
293+
) // MRBINDC_TRY
294+
}
295+
287296
MR_CSharp_E1 MR_CSharp_test_enum_MR_CSharp_E1(MR_CSharp_E1 a, const MR_CSharp_E1 *b)
288297
{
289298
MRBINDC_TRY(

test/output_c_fixed_typedefs/include/MR/test_csharp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,16 @@ MR_C_API int32_t MR_CSharp_test_constness_int(int32_t _1, const int32_t *_2);
870870
// Never returns null. Returns an instance allocated on the heap! Must call `MR_C_std_string_Destroy()` to free it when you're done using it.
871871
MR_C_API MR_C_std_string *MR_CSharp_test_constness_str(const char *_1, const char *_1_end, const char *_2, const char *_2_end);
872872

873+
// Test how we adjust keywords in parameter names.
874+
// \param params blah
875+
// @param params blah
876+
// `params` 'params' "params" params huhparams paramshuh \p params \c params @p params @c params \A params @A params
877+
// In this comment, only quoted and `\param ...` uses are adjusted, and not standalone occurences of the word (even if it's a separate word, let alone if it's just a part of a word).
878+
// `\c ...` and `\p ...` are handled, but unknown tags like `\A ...` are not.
879+
// <param name="params">This is also handled, naturally, because we handle quotes.</param>
880+
// Generated from function `MR::CSharp::test_keyword_in_param_name`.
881+
MR_C_API void MR_CSharp_test_keyword_in_param_name(int32_t params);
882+
873883
// Generated from function `MR::CSharp::test_enum`.
874884
// Parameter `b` has a default argument: `E1::b`, pass a null pointer to use it.
875885
MR_C_API MR_CSharp_E1 MR_CSharp_test_enum_MR_CSharp_E1(MR_CSharp_E1 a, const MR_CSharp_E1 *b);

test/output_c_fixed_typedefs/source/MR/test_csharp.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,13 @@ MR_C_std_string *MR_CSharp_test_constness_str(const char *_1, const char *_1_end
242242
));
243243
}
244244

245+
void MR_CSharp_test_keyword_in_param_name(int32_t params)
246+
{
247+
::MR::CSharp::test_keyword_in_param_name(
248+
params
249+
);
250+
}
251+
245252
MR_CSharp_E1 MR_CSharp_test_enum_MR_CSharp_E1(MR_CSharp_E1 a, const MR_CSharp_E1 *b)
246253
{
247254
using namespace MR;

test/output_c_fixed_typedefs_64_only/include/MR/test_csharp.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,16 @@ MR_C_API int MR_CSharp_test_constness_int(int _1, const int *_2);
867867
/// Never returns null. Returns an instance allocated on the heap! Must call `MR_C_std_string_Destroy()` to free it when you're done using it.
868868
MR_C_API MR_C_std_string *MR_CSharp_test_constness_str(const char *_1, const char *_1_end, const char *_2, const char *_2_end);
869869

870+
// Test how we adjust keywords in parameter names.
871+
// \param params blah
872+
// @param params blah
873+
// `params` 'params' "params" params huhparams paramshuh \p params \c params @p params @c params \A params @A params
874+
// In this comment, only quoted and `\param ...` uses are adjusted, and not standalone occurences of the word (even if it's a separate word, let alone if it's just a part of a word).
875+
// `\c ...` and `\p ...` are handled, but unknown tags like `\A ...` are not.
876+
// <param name="params">This is also handled, naturally, because we handle quotes.</param>
877+
/// Generated from function `MR::CSharp::test_keyword_in_param_name`.
878+
MR_C_API void MR_CSharp_test_keyword_in_param_name(int params);
879+
870880
/// Generated from function `MR::CSharp::test_enum`.
871881
/// Parameter `b` has a default argument: `E1::b`, pass a null pointer to use it.
872882
MR_C_API MR_CSharp_E1 MR_CSharp_test_enum_MR_CSharp_E1(MR_CSharp_E1 a, const MR_CSharp_E1 *b);

test/output_c_fixed_typedefs_64_only/source/MR/test_csharp.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ MR_C_std_string *MR_CSharp_test_constness_str(const char *_1, const char *_1_end
240240
));
241241
}
242242

243+
void MR_CSharp_test_keyword_in_param_name(int params)
244+
{
245+
::MR::CSharp::test_keyword_in_param_name(
246+
params
247+
);
248+
}
249+
243250
MR_CSharp_E1 MR_CSharp_test_enum_MR_CSharp_E1(MR_CSharp_E1 a, const MR_CSharp_E1 *b)
244251
{
245252
using namespace MR;

test/output_csharp/src/MR/test_csharp.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24207,6 +24207,23 @@ public static unsafe MR.CS.Std.String TestConstnessStr(string _1, string? _2 = n
2420724207
}
2420824208
}
2420924209

24210+
// Test how we adjust keywords in parameter names.
24211+
// \param params_ blah
24212+
// @param params_ blah
24213+
// `params_` 'params_' "params_" params huhparams paramshuh \p params_ \c params_ @p params_ @c params_ \A params @A params
24214+
// In this comment, only quoted and `\param ...` uses are adjusted, and not standalone occurences of the word (even if it's a separate word, let alone if it's just a part of a word).
24215+
// `\c ...` and `\p ...` are handled, but unknown tags like `\A ...` are not.
24216+
// <param name="params_">This is also handled, naturally, because we handle quotes.</param>
24217+
/// Generated from function `MR::CSharp::test_keyword_in_param_name`.
24218+
public static void TestKeywordInParamName(int params_)
24219+
{
24220+
[System.Runtime.InteropServices.DllImport("bleh", EntryPoint = "MR_CSharp_test_keyword_in_param_name", ExactSpelling = true)]
24221+
extern static void __MR_CSharp_test_keyword_in_param_name(int params_);
24222+
MR.CS.Misc._Exceptions.Prepare();
24223+
MR.CS.Misc._Exceptions.ThrowIfNeeded();
24224+
__MR_CSharp_test_keyword_in_param_name(params_);
24225+
}
24226+
2421024227
/// Generated from function `MR::CSharp::test_enum`.
2421124228
/// Parameter `b` defaults to `E1::b`.
2421224229
public static unsafe MR.CS.CSharp.E1 TestEnum(MR.CS.CSharp.E1 a, MR.CS.CSharp.E1? b = null)

0 commit comments

Comments
 (0)