Skip to content

Commit

Permalink
[dotnet][generator] Fix creating 3rd party bindings (#11522)
Browse files Browse the repository at this point in the history
Internally the generator uses `AvailabilityBaseAttribute` to make its
decisions. For `dotnet` we generated the newer `[SupportedOSPlatform]`
and `[UnsupportedOSPlatform]`.

A 3rd-party (dotnet) binding might refer to members decorated with the
newer attributes and fail the build with an error [1]. Avoiding the error
is easy (first block of the diff) but it does not make the _right_
decisions (e.g. if a member is unavailable for the platform) when
generating the code.

To fix this we need to be able to convert the new attributes into the
well know `AvailabilityBaseAttribute` subclasses. We have not spotted
such cases yet because

* the bindings pass our tests (good but extra code would not fail)
* API diff across legacy and dotnet is not yet done [2]

[1] #11497
[2] #10210
  • Loading branch information
spouliot authored May 12, 2021
1 parent 05e2a46 commit 1026b3f
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/generator-attribute-manager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ System.Type LookupReflectionType (string fullname, ICustomAttributeProvider prov
return typeof (Visibility);
case "WrapAttribute":
return typeof (WrapAttribute);
#if NET
case "System.Runtime.Versioning.SupportedOSPlatformAttribute":
return typeof (System.Runtime.Versioning.SupportedOSPlatformAttribute);
case "System.Runtime.Versioning.UnsupportedOSPlatformAttribute":
return typeof (System.Runtime.Versioning.UnsupportedOSPlatformAttribute);
#endif
}

switch (fullname) {
Expand Down Expand Up @@ -246,6 +252,9 @@ Type ConvertType (System.Type type, ICustomAttributeProvider provider)
case null: // Root namespace such as PlatformAvailabilityShadow.cs
case "MonoTouch.ObjCRuntime":
case "ObjCRuntime":
#if NET
case "System.Runtime.Versioning":
#endif
break;
default:
return Enumerable.Empty<System.Attribute> ();
Expand Down Expand Up @@ -281,11 +290,64 @@ Type ConvertType (System.Type type, ICustomAttributeProvider provider)
return AttributeFactory.CreateUnavailableAttribute (PlatformName.MacCatalyst).Yield ();
case "AvailabilityAttribute":
return AttributeConversionManager.ConvertAvailability (attribute);
#if NET
case "SupportedOSPlatformAttribute":
var sarg = attribute.ConstructorArguments [0].Value as string;
(var sp, var sv) = ParseOSPlatformAttribute (sarg);
return AttributeFactory.CreateNewIntroducedAttribute (sp, sv.Major, sv.Minor).Yield ();
case "UnsupportedOSPlatformAttribute":
var uarg = attribute.ConstructorArguments [0].Value as string;
(var up, var uv) = ParseOSPlatformAttribute (uarg);
// might have been available for a while...
if (uv == null)
return AttributeFactory.CreateUnavailableAttribute (up).Yield ();
else
return Enumerable.Empty<System.Attribute> ();
#endif
default:
return Enumerable.Empty<System.Attribute> ();
}
}

#if NET
static (PlatformName, Version) ParseOSPlatformAttribute (string arg)
{
PlatformName name;
int len;
switch (arg) {
case string s when s.StartsWith ("ios", StringComparison.Ordinal):
name = PlatformName.iOS;
len = "ios".Length;
break;
case string s when s.StartsWith ("tvos", StringComparison.Ordinal):
name = PlatformName.TvOS;
len = "tvos".Length;
break;
case string s when s.StartsWith ("watchos", StringComparison.Ordinal):
name = PlatformName.WatchOS;
len = "watchos".Length;
break;
case string s when s.StartsWith ("macos", StringComparison.Ordinal):
name = PlatformName.MacOSX;
len = "macos".Length;
break;
case string s when s.StartsWith ("maccatalyst", StringComparison.Ordinal):
name = PlatformName.MacCatalyst;
len = "maccatalyst".Length;
break;
default:
throw new BindingException (1047, arg);
}

Version version = null;
if (arg.Length > len) {
if (!Version.TryParse (arg [len..], out version))
throw new BindingException (1047, arg);
}
return (name, version);
}
#endif

IEnumerable<T> CreateAttributeInstance <T> (CustomAttributeData attribute, ICustomAttributeProvider provider) where T : System.Attribute
{
var convertedAttributes = ConvertOldAttributes (attribute);
Expand Down

1 comment on commit 1026b3f

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ [CI Build] Tests failed on Build ❌

Tests failed on Build.

API & Generator diff

API Diff (from PR only) (no change)
ℹ️ Generator Diff (please review changes)

Packages generated

View packages

Test results

1 tests failed, 192 tests passed.

Failed tests

  • introspection/watchOS 32-bits - simulator/Debug (watchOS 5.0): Failed

Pipeline on Agent XAMBOT-1023.BigSur'
[dotnet][generator] Fix creating 3rd party bindings (#11522)

Please sign in to comment.