Skip to content

Commit 19be370

Browse files
authored
[Java.Interop.Tools.Generator] Improve ExtractApiLevel() resiliency (#1365)
Context: f07b538 Context: https://github.com/jpobst/BindingStudio While using jpobst/BindingStudio to enumify API-36.1, it would crash: System.NotSupportedException: Could not parse `W` as an ApiLevel. at Java.Interop.Tools.Generator.AndroidSdkVersion.Parse(String value) in W:\src\jpobst\BindingStudio\external\Java.Interop\src\Java.Interop.Tools.Generator\Utilities\AndroidSdkVersion.cs:line 124 at Java.Interop.Tools.Generator.NamingConverter.ParseApiLevel(String value) in W:\src\jpobst\BindingStudio\external\Java.Interop\src\Java.Interop.Tools.Generator\Utilities\NamingConverter.cs:line 21 at Java.Interop.Tools.Generator.NamingConverter.ParseApiLevel(XElement element) in W:\src\jpobst\BindingStudio\external\Java.Interop\src\Java.Interop.Tools.Generator\Utilities\NamingConverter.cs:line 60 at Java.Interop.Tools.Generator.Enumification.MethodMapEntry.FromElement(XElement element, String parameterName) in W:\src\jpobst\BindingStudio\external\Java.Interop\src\Java.Interop.Tools.Generator\Enumification\MethodMapEntry.cs:line 41 at Java.Interop.Tools.Generator.Enumification.MethodMapEntry.FromElement(XElement element, String parameterName) in W:\src\jpobst\BindingStudio\external\Java.Interop\src\Java.Interop.Tools.Generator\Enumification\MethodMapEntry.cs:line 54 at Java.Interop.Tools.Generator.Enumification.MethodMapEntry.FromXml(XElement element)+MoveNext() in W:\src\jpobst\BindingStudio\external\Java.Interop\src\Java.Interop.Tools.Generator\Enumification\MethodMapEntry.cs:line 31 The cause of the crash is that the `api-36.1.xml` file it was processing had `//@merge.SourceFile` attributes with the value: merge.SourceFile="…Xamarin-Work/src/dotnet/android/build-tools/create-android-api/../../bin/BuildDebug/api/api-36.1.xml.in" Notice the `-Work` in the value. This was used by `ExtractApiLevel()` to try to find numbers after the `-`, but `W` was after the `-`, not numbers. This didn't previously matter because f07b538 noted: > *Note*: Changes to `NamingConverter.ParseApiLevel()` are largely a > nothing-burger because the dotnet/android side usually has metadata: > > <attr > api-since="36.1" > path="/api//*[contains(@merge.SourceFile,'api-CANARY.xml.in')]" > name="api-since">36.1</attr > > which explicitly adds/sets `//@api-since` based on the > `//@merge.SourceFile` value. However, when jpobst/BindingStudio is used, `src/Mono.Android/metadata` is *not* used, and `//@merge.SourceFile` is instead used. Improve `ParseApiLevel()` to check for an `api-` prefix before looking for trailing numeric data.
1 parent 02bceb0 commit 19be370

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

src/Java.Interop.Tools.Generator/Utilities/NamingConverter.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,14 @@ public static AndroidSdkVersion ParseApiLevel (string? value)
2727
if (!value.HasValue ())
2828
return null;
2929

30-
var hyphen = value.IndexOf ('-');
31-
if (hyphen < 0 || (hyphen+1) >= value.Length)
30+
const string ApiFilenamePrefix = "api-";
31+
32+
var hyphen = value.LastIndexOf (ApiFilenamePrefix);
33+
if (hyphen < 0 || checked (hyphen + 1 + ApiFilenamePrefix.Length) >= value.Length)
3234
return null;
35+
hyphen += ApiFilenamePrefix.Length;
3336

34-
int end = hyphen + 1;
37+
int end = hyphen;
3538
if (char.IsAsciiDigit (value [end++])) {
3639
for ( ; end < value.Length; ++end) {
3740
var n = value [end + 1];
@@ -46,7 +49,7 @@ public static AndroidSdkVersion ParseApiLevel (string? value)
4649
}
4750
}
4851

49-
return value.Substring (hyphen + 1, end - hyphen - 1);
52+
return value.Substring (hyphen, end - hyphen);
5053
}
5154

5255
// The 'merge.SourceFile' attribute may be on the element, or only on its parent. For example,

tests/Java.Interop.Tools.Generator-Tests/Utilities/NamingConverterTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public void ParseApiLevel ()
2222
Assert.AreEqual (28, v.ApiLevel);
2323
Assert.AreEqual (0, v.MinorRelease);
2424

25+
v = NamingConverter.ParseApiLevel (@"…\Xamarin-Work\…\bin\BuildDebug\api\api-36.1.xml.in");
26+
Assert.AreEqual (36, v.ApiLevel);
27+
Assert.AreEqual (1, v.MinorRelease);
28+
2529
v = NamingConverter.ParseApiLevel (@"..\..\bin\BuildDebug\api\api-36.1.xml.in");
2630
Assert.AreEqual (36, v.ApiLevel);
2731
Assert.AreEqual (1, v.MinorRelease);

0 commit comments

Comments
 (0)