Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

Commit 61cdb40

Browse files
[generator] Fix reserved keywords binary search (#977)
Context: 7068f4b Context: https://docs.microsoft.com/en-us/dotnet/core/extensions/performing-culture-insensitive-string-operations-in-arrays Commit 7068f4b enabled string code analyzers, because in e.g. the `sr` locale, `"Ljava".StartsWith("L")` would be *false*, because `Lj` was a language-specific digraph, and "special-cased". For intended behavior, we need to use `.StartsWith("L", StringComparison.Ordinal)`. There is a ["similar yet different" problem][0] with `Array.Sort()` and `Array.BinarySearch()` and string arrays: a locale-specific comparison is performed by default: var reserved_keywords = new [] { "as", "catch", "char", "checked", "class", "const", }; var index = Array.BinarySearch (reserved_keywords, "checked"); The *expectation* is that `index` is 3. In the `cs-CZ` locale, "ch" is a digraph, and `index` is -7, i.e. was not found. There is currently no Code Analysis check for this scenario. Review all `Array.Sort()` and `Array.BinarySearch()` invocations so that an appropriate `IComparer` instance is provided. This allows e.g. `checked` to be properly `@escaped` when created a binding in a machine with a `cs-CZ` locale. [0]: https://docs.microsoft.com/en-us/dotnet/core/extensions/performing-culture-insensitive-string-operations-in-arrays
1 parent 2a882d2 commit 61cdb40

4 files changed

Lines changed: 31 additions & 5 deletions

File tree

‎tests/generator-Tests/Unit-Tests/CodeGenerationOptionsTests.cs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
usingSystem;
1+
usingSystem.Collections.Generic;
2+
usingSystem.Linq;
23
usingMonoDroid.Generation;
34
usingNUnit.Framework;
45

@@ -79,5 +80,17 @@ public void GetTypeReferenceName_Nullable ()
7980

8081
Assert.AreEqual("uint",opt.GetTypeReferenceName(primitive_uint));
8182
}
83+
84+
[Test,TestCaseSource(nameof(ReservedKeywords))]
85+
[SetCulture("cs-CZ")]
86+
publicvoidGetSafeIdentifierCultureInvariant(stringkeyword)
87+
{
88+
varopt=newCodeGenerationOptions();
89+
90+
Assert.AreEqual($"{keyword}_",opt.GetSafeIdentifier(keyword));
91+
}
92+
93+
privatestaticIEnumerable<TestCaseData>ReservedKeywords
94+
=>TypeNameUtilities.reserved_keywords.Select(keyword =>newTestCaseData(keyword));
8295
}
8396
}

‎tests/generator-Tests/Unit-Tests/TypeNameUtilitiesTests.cs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
usingSystem;
1+
usingSystem.Collections.Generic;
2+
usingSystem.Linq;
23
usingMonoDroid.Generation;
34
usingNUnit.Framework;
45

@@ -19,5 +20,17 @@ public void MangleName ()
1920
Assert.AreEqual("byte_var",TypeNameUtilities.MangleName("byte_var"));
2021
Assert.AreEqual("foo",TypeNameUtilities.MangleName("foo"));
2122
}
23+
24+
[Test,TestCaseSource(nameof(ReservedKeywords))]
25+
[SetCulture("cs-CZ")]
26+
publicvoidMangleNameCutlureInvariant(stringkeyword)
27+
{
28+
Assert.AreEqual($"@{keyword}",TypeNameUtilities.MangleName(keyword));
29+
}
30+
31+
privatestaticIEnumerable<TestCaseData>ReservedKeywords
32+
=>TypeNameUtilities.reserved_keywords
33+
.Where(keyword =>keyword!="event")// "event" is a special case which is mapped to "e" instead of "@event"
34+
.Select(keyword =>newTestCaseData(keyword));
2235
}
2336
}

‎tools/generator/CodeGenerationOptions.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ public string GetSafeIdentifier (string name)
267267
// (ReturnValue.ToNative() takes an argument which could be either an expression or mere symbol.)
268268
if(name[name.Length-1]!=')'&&!name.Contains('.')&&!name.StartsWith("@",StringComparison.Ordinal)){
269269
if(!IdentifierValidator.IsValidIdentifier(name)||
270-
Array.BinarySearch(TypeNameUtilities.reserved_keywords,name)>=0){
270+
Array.BinarySearch(TypeNameUtilities.reserved_keywords,name,StringComparer.Ordinal)>=0){
271271
name=name+"_";
272272
}
273273
}

‎tools/generator/Utilities/TypeNameUtilities.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ public static string MangleName (string name)
8080
{
8181
if(name=="event")
8282
return"e";
83-
84-
if(Array.BinarySearch(reserved_keywords,name)>=0)
83+
84+
if(Array.BinarySearch(reserved_keywords,name,StringComparer.Ordinal)>=0)
8585
return"@"+name;
8686

8787
returnname;

0 commit comments

Comments
 (0)